92. 反转链表 II

92. 反转链表 II

其中left和right分别表示要反转的部分的起始和结束位置(从1开始计数)。整个过程分为两个主要步骤:

将p0移动到反转部分的前一个节点。
通过循环反转从left到right部分的链表。
最后,通过调整指针,将反转后的部分重新连接到原链表中。

假设我们有一个链表和给定的leftright值,我们要反转从位置left到位置right的链表部分。以下是可视化的过程,以链表1->2->3->4->5为例,left=2right=4,目标是反转从节点2到节点4的部分。

初始链表状态:

dummy -> 1 -> 2 -> 3 -> 4 -> 5
         ↑
         p0 (初始位置)
  1. 移动p0left-1的位置,即节点1的位置。
dummy -> 1 -> 2 -> 3 -> 4 -> 5
         ↑
         p0
  1. 开始反转从leftright的部分。我们使用precur指针来帮助我们进行反转。pre初始化为nullcur初始化为p0.next,即开始反转的第一个节点。

第一次迭代:

pre = null, cur = 2

dummy -> 1    2 -> 3 -> 4 -> 5
         ↑    ↑
         p0   cur
              pre

第二次迭代:

pre = 2, cur = 3

dummy -> 1    2 <- 3 -> 4 -> 5
         ↑         ↑
         p0        cur
                    pre

第三次迭代:

pre = 3, cur = 4

dummy -> 1    2 <- 3 <- 4 -> 5
         ↑              ↑
         p0             cur
                         pre
  1. 完成反转后,重新连接链表的各个部分。将p0.next.next指向cur,将p0.next指向pre
dummy -> 1 -> 4 -> 3 -> 2 -> 5
         ↑              ↑
         p0             cur
                         pre

最终结果:

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

通过这个过程,我们成功地反转了从位置2到位置4的链表部分。

在链表反转的过程中,curprenxt三个指针各自承担着不同的角色和职责:

  1. cur(当前节点指针):

    • cur指向当前正在处理的节点。
    • 在反转过程中,cur会逐步沿着原链表向前移动。
    • cur的作用是标记当前操作的节点,确保反转操作能够按顺序逐个节点进行。
  2. pre(前置节点指针):

    • pre指向当前节点cur的前一个节点。
    • 在反转过程中,pre用于保存cur的前一个节点的信息,因为在反转curnext指针指向pre之后,原链表中cur的前一个节点的信息会丢失。
    • pre的作用是在反转时,将当前节点curnext指针指向它,实现反转。
  3. nxt(下一个节点指针):

    • nxt临时存储cur的下一个节点,即cur.next
    • 在反转curnext指针之前,需要先保存cur.next的信息到nxt,因为一旦cur.next被更新指向precur原本的下一个节点信息就会丢失。
    • nxt的作用是确保在反转过程中不会丢失对原链表中cur后续节点的访问。

通过这三个指针的协作,可以实现链表的局部或完整反转,同时保证链表的连续性和完整性不被破坏。在反转过程中,cur会逐步向前移动,prenxt分别帮助实现反转操作和保持链表的连续性。

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        // 创建一个哑节点,其next指向head,简化边界条件处理
        ListNode dummy = new ListNode(0, head), p0 = dummy;
        // 将p0移动到反转部分的前一个节点
        for (int i = 0; i < left - 1; ++i)
            p0 = p0.next;
        // 开始反转链表的部分
        ListNode pre = null, cur = p0.next;
        for (int i = 0; i < right - left + 1; ++i) {
            ListNode nxt = cur.next;
            cur.next = pre; // 反转指针
            pre = cur;
            cur = nxt;
        }
        // 将反转部分与原链表连接
        p0.next.next = cur;
        p0.next = pre;
        // 返回哑节点的下一个节点,即新的头节点
        return dummy.next;
    }
}
posted @ 2024-07-10 08:09  economies  阅读(24)  评论(0)    收藏  举报