给你单链表的头指针 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
进阶: 你可以使用一趟扫描完成反转吗?
以下是反转链表指定区间的 Java 实现。代码使用虚拟头节点简化边界情况处理,并通过四步定位法完成反转操作:
java
复制
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
*/
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
// 创建虚拟头节点简化操作
ListNode dummy = new ListNode(-1, head);
ListNode prev = dummy;
// Step 1: 定位 left 前一个节点
for (int i = 0; i < left - 1; i++) {
prev = prev.next;
}
// Step 2: 定位三个关键节点
ListNode leftNode = prev.next;
ListNode curr = prev.next;
ListNode next;
// Step 3: 反转区间链表
ListNode newTail = leftNode; // 反转后的新尾部
ListNode preReverse = null; // 反转前驱指针
// 反转指定区间内的链表
for (int i = 0; i < right - left + 1; i++) {
next = curr.next;
curr.next = preReverse;
preReverse = curr;
curr = next;
}
// Step 4: 重新连接链表
prev.next = preReverse; // 连接左段
newTail.next = curr; // 连接右段
return dummy.next;
}
}
算法思路说明:
-
虚拟头节点:创建 dummy 节点指向头节点,处理 left=1 的反转情况
-
四步定位:
prev
:指向 left 前一个节点leftNode
:反转区间起始节点(反转后成为新尾部)preReverse
:反转区间后的新头节点curr
:反转区间后的下一个节点
-
反转过程:
-
遍历从 left 到 right 的节点
-
采用标准的链表反转三指针法:
java 复制 next = curr.next; // 临时保存后续节点 curr.next = prev; // 反转指针方向 prev = curr; // 移动前驱指针 curr = next; // 移动当前指针
-
-
重新连接:
- 将反转后的链表头 (
preReverse
) 连接到左段 (prev.next
) - 将反转后的链表尾 (
newTail
) 连接到右段 (curr
)
- 将反转后的链表头 (
复杂度分析:
-
时间复杂度:O(n)
- 最坏情况需要完整遍历整个链表(当 left=1, right=n 时)
- 实际操作只需完成单次遍历
-
空间复杂度:O(1)
- 仅使用常量额外空间(几个指针变量)
示例验证:
示例 1:head = [1,2,3,4,5], left=2, right=4
-
定位:prev=1, leftNode=2, newTail=2
-
反转区间:
- 反转 [2,3,4] → [4,3,2]
- preReverse=4, curr=5
-
连接:
- 1 → 4(左段连接)
- 2 → 5(右段连接)
- 结果:1 → 4 → 3 → 2 → 5
示例 2:head = [5], left=1, right=1
- 定位:prev=dummy, leftNode=5, newTail=5
- 反转区间:单个节点不变
- 连接:dummy → 5 → null
- 返回 [5]
此实现满足题目要求,能正确处理各种边界情况(包括从头反转、反转整个链表等特殊情况)。