92. 反转链表 II - 力扣(LeetCode)
题目:
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
示例 1:

输入:head = [1,2,3,4,5], left = 2, right = 4 输出:[1,4,3,2,5]
示例 2:
输入:head = [5], left = 1, right = 1 输出:[5]
提示:
-
链表中节点数目为
n -
1 <= n <= 500 -
-500 <= Node.val <= 500 -
1 <= left <= right <= n
思路如下:
这道题是链表反转的进阶版,只要求反转链表内部的一段链表,反转完成后再与为反转链表部分连接。因此首先要确定反转链表的头 left 尾 right 位置,这里引用虚拟节点 dummy = ListNode(0) ,设定在头节点时 count = 1,找到 left 的前一个节点 pre,则 pre.next 就是 left 的位置。
当 count 记数值等于 left 节点值时,设定第一个反转节点位置指针为 cur ,反转结束后的尾节点 tail 也在此。设定 cur 节点的后一个节点指针为 nxt ,反转开始。第一次反转,将 cur.next 指向 pre.next 为自身,因此跳过。第二次循环,cur 指向 nxt 的位置,进行题解代码的操作......直到最后 count <= right,返回头节点。
题解如下:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:zj
def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
count = 1
dummy = ListNode(0)
dummy.next = head
pre = dummy
# 未开始反转,寻找反转节点前的位置
while pre.next and count < left:
pre = pre.next
count += 1
cur = pre.next
tail = cur
while cur and count <= right:
nxt = cur.next
# 反转开始节点即是 cur 也是 tail,所以反转后仍是自己
# cur 右移一步后开始反转
cur.next = pre.next # cur 的 next 指针指向 pre 的 next
pre.next = cur # pre 连接原来 tail 的指针断开 指向 cur
tail.next = nxt # 原来 tail 的指针指向 nxt
# cur 指向 nxt 的位置
cur = nxt
count += 1
return dummy.next
题解示例:
假设链表为 1->2->3->4->5->NULL,left = 2,right = 4:
初始状态:
dummy 指向虚拟头节点,dummy.next 指向节点 1。
pre 移动到节点 1,count 增加到 2。
反转指定区间内的节点:
初始化 cur 为节点 2,tail 为节点 2。
第一次循环(count = 2):
nxt 指向节点 3。
cur.next 指向 pre.next(节点 1 的 next 是节点 2,所以 cur.next 指向节点 2,形成循环)。
pre.next 更新为 cur(节点 2),形成循环。
tail.next 指向 nxt(节点 3),保持剩余链表的连接。
cur 移动到 nxt(节点 3),count 增加到 3。
第二次循环(count = 3):
cur 指向节点 3。
nxt 指向节点 4。
cur.next 指向 pre.next(节点 2),将节点 3 插入到节点 2 后面。
pre.next 断开与节点 2 的连接,更新为 cur(节点 3)。
此时节点 2 tail.next 指向 nxt(节点 4),保持剩余链表的连接。
cur 移动到 nxt(节点 4),count 增加到 4。
第三次循环(count = 4):
nxt 指向节点 5。
cur.next 指向 pre.next(节点 3),将节点 4 插入到节点 3 后面。
pre.next 更新为 cur(节点 4)。
tail.next 指向 nxt(节点 5),保持剩余链表的连接。
cur 移动到 nxt(节点 5),count 增加到 5,循环结束。
最终状态:
pre.next 指向节点 4,tail.next 指向节点 5。
链表结构为 1->4->3->2->5->NULL。
逻辑梳理:
-
初始化计数器和虚拟头节点:
-
count = 1:用于记录当前节点的位置。 -
dummy = ListNode(0):创建一个虚拟头节点,其next指向原链表的头节点。这有助于简化对头节点的处理。 -
pre = dummy:pre指针初始化为虚拟头节点。
-
-
找到反转部分的前一个节点:
-
使用
while循环将pre指针移动到反转部分的前一个节点。例如,当left = 2时,pre会移动到节点1。
-
-
初始化指针:
-
cur = pre.next:cur指针初始化为反转部分的第一个节点。 -
tail = cur:tail指针初始化为反转部分的第一个节点,用于后续连接剩余链表。
-
-
反转指定区间内的节点:
-
使用
while循环逐步反转链表的指定部分。 -
nxt = cur.next:保存当前节点的下一个节点,避免断链。 -
cur.next = pre.next:将当前节点的next指针指向pre.next,实现当前节点的反转。 -
pre.next = cur:将当前节点插入到pre指针之后。 -
tail.next = nxt:更新tail指针的next,保持剩余链表的连接。 -
移动
cur指针到下一个需要处理的节点,并更新计数器。
-
-
返回结果:
-
最终返回
dummy.next,即反转后的链表头节点。
-
更多推荐

所有评论(0)