反转从位置 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 not head or not head.next or m==n: #不先处理这些情况会慢一些
return head
dummy = ListNode(0)
dummy.next = head # 头插法
pre = dummy #dummy留着不动,用来最后返回
for _ in range(m-1):
pre = pre.next #到要处理的节点的前一个
tail = pre.next #第m个节点,处理完后是末尾的n位置节点
cur = pre.next.next
for _ in range(n-m): #反转
tmp = pre.next
tmp1 = cur.next
pre.next = cur #pre的位置是不动的,一直往pre后面插当前cur节点
cur.next = tmp
cur = tmp1
tail.next = cur #反转完后cur指向最后不用反转的部分,把它连上去
return dummy.next
比照示例,这种方法就是往m-1位置后面一直插节点。因为pre部分一直连着要反转的部分,所以只要最后连接tail部分就好
整个dummy的变化:
0->1->3<->2 4->5->NULL
0->1->4->3<->2 5->NULL # 这里如果不把2.next指针指向5会死循环超出时间限制
0->1->4->3->2->5->NULL
这里把dummy放到最开头是为了避免m=1的情况处理不到
方法二:指针反转
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
if not head or not head.next or m==n:
return head
dummy = ListNode(0)
dummy.next = head
prehead = dummy #不用反转的前面部分
for i in range(m-1):
prehead = prehead.next
cur = prehead.next #开始反转的位置
tail = prehead.next
pre = None #一个空的前向指针
for i in range(n-m+1): #这里n-m+1,才能pre指向n,cur指向n+1
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
prehead.next = pre #前连中
tail.next = cur # 连上尾
return dummy.next
参照实例,反转后dummy:0->1->2, pre:2<-3<-4 , cur:5->NULL
连起来:1,2之间断掉 0->1->4->3->2 ,再用2接上5,dummy:0->1->4->3->2->5->NULL
这里不在最前面插dummy也处理不了m=1的情况
写成这样更快一点,方法差不多
# 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
dummy = ListNode(0)
dummy.next = head
a, d = dummy, dummy
for _ in range(m - 1):
a = a.next
for _ in range(n):
d = d.next
b, c = a.next, d.next
pre = b
cur = pre.next
while cur != c:
next = cur.next
cur.next = pre
pre = cur
cur = next
a.next = d
b.next = c
return dummy.next
笨办法也可以过:用list存处理好了再接上去
# 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 not head or not head.next or m==n:
return head
res = []
while(head):
res.append(head.val)
head = head.next
lista = res[:m-1]
listb = res[m-1:n][::-1]
listc = res[n:]
lista.extend(listb)
lista.extend(listc)
cur = ListNode(0)
dummy = cur
for i in lista:
cur.next = ListNode(i)
cur = cur.next
return dummy.next