LeetCode 92. 反转链表 II - 算法解析

发布于:2025-09-01 ⋅ 阅读:(15) ⋅ 点赞:(0)

LeetCode 92. 反转链表 II - 算法解析

问题描述

给你单链表的头指针 head 和两个整数 left 和 right,其中 left <= right。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表。

代码实现

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        if(head==null || head.next==null){
            return head;
        }
        ListNode dummy = new ListNode(0,head);
        ListNode preLeft = dummy;
        for (int i = 0; i < left - 1; i++) {
            preLeft=preLeft.next;
        }
        ListNode pre=null,cur=preLeft.next;
        for (int i = 0; i < right - left + 1; i++) {
            ListNode nxt = cur.next;
            cur.next= pre;
            pre=cur;
            cur=nxt;
        }
        preLeft.next.next=cur;
        preLeft.next=pre;
        return dummy.next;
    }
}

算法思路

这个算法采用原地反转的方式,分为以下几个关键步骤:

1. 边界处理和初始化

if(head==null || head.next==null){
    return head;
}
ListNode dummy = new ListNode(0,head);
  • 处理空链表或单节点链表的边界情况
  • 创建虚拟头节点dummy,简化边界处理(特别是当left=1时)

2. 找到反转区间的前一个节点

ListNode preLeft = dummy;
for (int i = 0; i < left - 1; i++) {
    preLeft=preLeft.next;
}
  • preLeft指向第left个节点的前一个节点
  • 这个节点很关键,因为反转后需要重新连接

3. 反转指定区间的链表

ListNode pre=null,cur=preLeft.next;
for (int i = 0; i < right - left + 1; i++) {
    ListNode nxt = cur.next;
    cur.next= pre;
    pre=cur;
    cur=nxt;
}

这是标准的链表反转操作:

  • pre: 前一个节点(初始为null)
  • cur: 当前节点(从第left个节点开始)
  • nxt: 下一个节点(临时保存)

反转过程

  1. 保存下一个节点:nxt = cur.next
  2. 反转当前节点的指针:cur.next = pre
  3. 移动指针:pre = cur, cur = nxt
  4. 重复right - left + 1

4. 重新连接链表

preLeft.next.next=cur;
preLeft.next=pre;
  • preLeft.next.next=cur: 将原来的第left个节点(现在是反转区间的尾节点)连接到反转区间后面的节点
  • preLeft.next=pre: 将preLeft连接到反转后的头节点

图解示例

head = [1,2,3,4,5], left = 2, right = 4为例:

初始状态

dummy -> 1 -> 2 -> 3 -> 4 -> 5 -> null
         ^    ^         ^
     preLeft  |         |
            反转区间起点 反转区间终点

找到preLeft

dummy -> 1 -> 2 -> 3 -> 4 -> 5 -> null
         ^
     preLeft

反转过程

第1次反转

pre=null, cur=2, nxt=3
2.next = null
pre=2, cur=3

第2次反转

pre=2, cur=3, nxt=4
3.next = 2
pre=3, cur=4

第3次反转

pre=3, cur=4, nxt=5
4.next = 3
pre=4, cur=5

重新连接

preLeft.next.next = cur  // 2.next = 5
preLeft.next = pre       // 1.next = 4

最终结果

dummy -> 1 -> 4 -> 3 -> 2 -> 5 -> null

返回[1,4,3,2,5]
在这里插入图片描述

复杂度分析

  • 时间复杂度:O(n)

    • 第一个循环:O(left) ≤ O(n)
    • 第二个循环:O(right - left + 1) ≤ O(n)
    • 总体:O(n)
  • 空间复杂度:O(1)

    • 只使用了常数个额外变量
    • 原地反转,没有使用额外的数据结构