题目描述
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reverse-linked-list-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
其实这是链表翻转的变种,以前我使用的链表翻转一直是插入法,即把后面的节点插入到前面中间去,这样需要保存插入位置。
代码如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
if m == n : return head
# 添加一个前驱节点
result = ListNode(0)
result.next = head
num = 0
cur = result
while num < m-1 :
cur = cur.next
num += 1
# 当前节点的下一个节点为m,翻转节点从这里开始插入
if num == m - 1 :
mprenode = cur
revnodehead = cur.next # 翻转节点头
revnodeend = cur.next # 设置翻转尾节点
cur = cur.next # cur设置为翻转范围内的第一个节点
num += 1
while (m <= num+1 <= n) :
# 从第二个节点开始翻转
if m+1 <= num+1 <= n:
# 翻转节点
temp = cur.next
cur.next = temp.next # 因为n小于链表长度,所以temp肯定存在
temp.next = revnodehead # 断开temp的后续节点 插入到翻转头之前
revnodehead = temp # 更新翻转节点头
num += 1
mprenode.next = revnodehead # 连接翻转节点头
revnodeend.next = cur.next # 节点尾
return result.next
链表翻转还可以有另外一种方法,我称之为掉落法,把第一个要翻转的节点从前面切断,它的后面节点依次切断,翻转连接的方向,然后依次向后遍历,最后把最后一个节点和原序列连接。
class Solution:
# @param head, a ListNode
# @param m, an integer
# @param n, an integer
# @return a ListNode
def reverseBetween(self, head, m, n):
if m == n:
return head
dummyNode = ListNode(0)
dummyNode.next = head
pre = dummyNode
for i in range(m - 1):
pre = pre.next
# reverse the [m, n] nodes
reverse = None
cur = pre.next
for i in range(n - m + 1):
next = cur.next
cur.next = reverse
reverse = cur
cur = next
pre.next.next = cur
pre.next = reverse
return dummyNode.next