LeetCode 92
Reverse a linked list from position m to n. Do it in one-pass. 注意必须使用O(n)的复杂度来实现
Note: 1 ≤ m ≤ n ≤ length of list.
Example:
Input: 1->2->3->4->5->NULL, m = 2, n = 4 Output: 1->4->3->2->5->NULL
思路:一开始的思路是使用start指针,找到第一个要换的位置p1,然后再通过遍历去找到交换的位置p2,接着进行互换。但这种算法的复杂度是o(n+k*2)。
我们希望能够有两个指针:ptr1,ptr2,ptr1指向交换的开始,ptr2指向交换的结束。每次交换将ptr1前进一位,将ptr2回退一位直到相交。
问题:但是因为这是一个单链表,无法直接从一个位置取得它的前一个node,所以我们需要用一个方法来得到前一个node
解决方法:使用递归的方法来取得上一位,根据递归的特性,每次返回都会从stack中取出上一次调用的局部变量,我们刚好可以通过这个特性来取得一个NODE的前一个NODE。(因为我们通过node.next来调用递归)
大体思路:
1.先通过递归来将left和right指针移动到交换起始和结束位置。
2.将left和right的值交换后返回上一次调用. 这样返回后right就指向前一次的node了。
但是left会在返回的时候向前移动,如何让他向后移动呢?
我们将left保存为全局变量,手动在每次交换后让left = left.next.
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
left, right = head, head
stop = False # 判断停止交换的flag
ptr = head
if head == None:
return head
def oneStep(right, m, n):
# exit
nonlocal left, stop #定义使用全局变量left和stop
if m > 1:
left = left.next #移动到交换的开始位置
if n == 0:
return #移动到交换的结束位置的后一位,返回
else:
oneStep(right.next, m-1, n-1) #如果还没到结尾,递归向后
if left== right or right.next == left: #停止交换
stop = True
if stop == False:
left.val, right.val = right.val, left.val
left = left.next
oneStep(ptr, m, n)
return head