LeetCode之Reverse Linked List II-python遞歸解法

題:
Reverse a linked list from position m to n. Do it in one-pass.

Note: 1 ≤ mn ≤ length of list.

Example:

Input: 1->2->3->4->5->NULL, m = 2, n = 4
Output: 1->4->3->2->5->NULL

一般的鏈表翻轉是將整個鏈表翻轉,其圖解方法可以參見:Python劍指offer之反轉鏈表-圖解

這道題的一般解法是:首先要添加一個新的頭節點,這樣可以解決當前頭節點發生變動的情況,這是必備套路;然後將3插入到1和2之間,再將4插入到1和3之間。

1 -> 2 -> 3 -> 4 -> 5 -> NULL

1 -> 3 -> 2 -> 4 -> 5 -> NULL

1 -> 4 -> 3 -> 2 -> 5 -> NULL

在解釋遞歸解法之前,思考一下對數組的翻轉,可以用前後兩個指針,向中間移動,同時交換位置

鏈表的遞歸解法也借用了上面的思路,而且非常巧妙,用了一個trick:用遞歸來實現鏈表的回溯,因爲鏈表不像數組,可以從後往前遍歷,但藉助遞歸,實際也就是棧,可以實現這一操作,下面爲對應的python代碼。

class Solution:
    def reverseBetween(self, head, m, n):
        if not head:
            return None

        left, right = head, head
        stop = False
        def recurseAndReverse(right, m, n):
            nonlocal left, stop
            if n == 1:
                return
            right = right.next
            if m > 1:
                left = left.next
            recurseAndReverse(right, m - 1, n - 1)
            if left == right or right.next == left:
                stop = True  
            if not stop:
                left.val, right.val = right.val, left.val
                left = left.next           

        recurseAndReverse(right, m, n)
        return head

代碼中的 nonlocal left, stop 非常關鍵,將 left, stop 設置爲了局部的全局變量,這一就可以在recurseAndReverse函數中改變外部變量left, stop的值,而right是recurseAndReverse函數的內部變量,會在遞歸返回的時候回溯到上一個節點,而left則直接next到下一個節點,實現了和翻轉數組一樣的操作。

既然翻轉鏈表的升級版可以這麼操作,那一般情況就更不在話下了,如下:

def reverse_list(head):
    if not head or not head.next:
        return head
    left, right = head,head
    stop = False
    def recurseAndReverse(right):
        nonlocal left, stop
        if not right: return
        helper(right.next)
        if left == right or right.next == left:
            stop = True
        if not stop:
            left.val, right.val = right.val, left.val
            left = left.next
    recurseAndReverse(right)
    return head
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章