題目 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))