反轉鏈表之遞歸操作鏈表

題目 92. 反轉鏈表 II

反轉從位置 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(object):
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution(object):
    def reverseBetween(self, head, m, n):
        '''
        用遞歸方式反轉鏈表的前n個節點,注意要記錄第n+1個節點(爲反轉後鏈表的後繼節點),
        返回反轉後的子鏈表的頭指針
        '''
        successor = None
        def reverse(head, n):
            global successor
            if n == 1:
                successor = head.next  # 反轉後鏈表的後繼節點
                return head
            # 把reverse(head.next, n-1)看做是:
            # 一個已經實現了 反轉以head.next爲頭結點的前n-1個節點的功能,且返回了新的頭結點(last)。(參照上兩張圖片)
            # 不要跳進遞歸,⽽是利⽤明確的定義來實現算法邏輯。
            last = reverse(head.next, n-1)  
            head.next.next = head
            head.next = successor
            return last

        # 整個都採用遞歸方式
        # if m == 1:
        #     return self.reverse(head, 1, n)
        # else:
        #     return self.reverseBetween(head.next, m-1, n-1)

        # 邊緣情況
        if m == n:
            return head
        if m == 1:
            return reverse(head, n)

        # 迭代,找第m-1個節點
        res = head  # 最終的頭結點
        t = m
        while t > 2 and head.next != None:
            head = head.next
            t -= 1
        precursor = head  # 第m-1個節點即爲 反轉後的子鏈表的前驅節點

        last = reverse(head.next, n-m+1)  # 需要注意是n-m+1,last爲需要反轉以後的子鏈表的頭結點
        precursor.next = last
        return res

# s = Solution()
# node1 = ListNode(1)
# node2 = ListNode(2)
# node3 = ListNode(3)
# node4 = ListNode(4)
# node5 = ListNode(5)
# node1.next = node2
# node2.next = node3
# node3.next = node4
# node4.next = node5
# node5.next = None
# print_list(node1)
# # print_list(s.reverseBetween(node1, 1, 4))
# print_list(s.reverseBetween(node1, 2, 4))
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章