'''
leetcode 92. 反转链表 II
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
算法:设置指针记录关键节点的索引位置,一共需要记录4个节点的位置
before 表示当前需要进行反转的子序列前一个节点,一旦找到before的位置,在整个程序运行过程中它不会发生改变
start 表示当前进行反转的子序列(在上次循环中)的起始节点
end 表示当前进行反转的子序列(在上次循环中)的尾部节点
curr 表示当前扫描到的节点,可能需要将curr节点加入到反转的子序列中
则所要求的功能的实现过程可以是:将所有在需要反转区间的节点curr(在原始单向链表中索引下标为m~n之间的节点)
加入到初始长度为1(初始的反转子序列只包含一个节点,即索引下标为m的节点,这意味着初始情况下start=end=反转子序列的第一个节点)
则每次将curr节点加入到反转子序列的过程可以分成如下3步完成:
(1)before.next=curr
(2)end.next=curr.next
(3)curr.next=start
curr节点的遍历范围:从索引下标为m+1的节点到索引下标为n的节点(边界的索引下标值均可以取到)
'''
# 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 head is None or head.next is None or m==n:
return head
new_head=ListNode(-float("inf"))
new_head.next=head
before=new_head
temp=m-1
while(temp):# 首先找到第一个需要被反转的节点的前驱的索引下标,在原始的head列表中,节点的索引下标从1开始
before=before.next
temp-=1
start=before.next
end=before.next
# before.next指向的是第一个需要被反转的节点,初始情况下被反转的子序列中只包含一个节点,就是第一个需要被反转的节点
# 在程序运行的整个过程中,end节点不会发生改变
if start.next==None:# 如果索引下标为m的节点是链表中的最后一个节点,则直接返回原始链表
return new_head.next
interval=n-m
curr=start.next
while(interval):
# 对于在需要进行反转的区间中的每个节点
before.next = curr
# print(before.next.val,'fsdjosadksa')
end.next = curr.next
saved=curr.next
curr.next = start
interval-=1
start=curr# 将curr节点加入到反转子序列中之后,反转子序列的第一个节点就是curr节点
curr=saved
while(head):
# print('here',head.val)
head=head.next
return new_head.next
if __name__=="__main__":
new_head=ListNode(0)
curr=new_head
for i in range(1,6):
new_node=ListNode(i)
new_head.next=new_node
new_head=new_head.next
output=Solution().reverseBetween(curr.next,2,4)
while(output):
print(output.val)
output=output.next