8.8 92. 反转链表 II
给你单链表的头指针 head
和两个整数 left
和 right
,其中 left <= right
。请你反转从位置 left
到位置 right
的链表节点,返回 反转后的链表 。
我的思路:找到左右的指针,切割出一段链表,反转之后又插回去。
看起来挺简单的,其实难得我不想说话。
1、创建一个虚拟头指针->解决只有一个数据的问题
const dummy = new ListNode(0);
dummy.next = head;
2、定位到切割链表的前一个节点font
let font = dummy;
for (let i = 0; i < left - 1; i++) {
font = font.next;
}
3、定位待反转区间的头节点 leftP 和尾节点 rightP
let leftP = font.next;
let rightP = leftP;
for (let i = 0; i < right - left; i++) { // 从 leftP 开始走 right-left 步
rightP = rightP.next;
}
4、切断链表
const back = rightP.next;
rightP.next = null; // 将子链表尾部切断,方便反转
5、进行翻转:
const reserveList = function(head){
let pre = null;
let curr = head;
while(curr){
const next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}
const reversedHead = reserveList(leftP);
6、拼接回去
font.next = reversedHead; // 前驱节点 -> 新头
leftP.next = back; // 新尾(原头) -> 后续节点
整体代码:
var reverseBetween = function(head, left, right) {
// 1. 创建虚拟头节点,并连接到原链表头:解决出现left=1的情况
const dummy = new ListNode(0);
dummy.next = head;
// 2. 定位到待反转区间的前一个节点 font
let font = dummy;
for (let i = 0; i < left - 1; i++) {
font = font.next;
}
// 3. 定位待反转区间的头节点 leftP 和尾节点 rightP
let leftP = font.next;
let rightP = leftP;
for (let i = 0; i < right - left; i++) { // 从 leftP 开始走 right-left 步
rightP = rightP.next;
}
// 4. 切断链表,并保存后续节点
const back = rightP.next;
rightP.next = null; // 将子链表尾部切断,方便反转
// 5. 反转子链表
const reversedHead = reserveList(leftP);
// 6. 将反转后的子链表拼回原链表
font.next = reversedHead; // 前驱节点 -> 新头
leftP.next = back; // 新尾(原头) -> 后续节点
// 7. 返回新的链表头(虚拟头节点的下一个)
return dummy.next;
};
const reserveList = function(head){
let pre = null;
let curr = head;
while(curr){
const next = curr.next;
curr.next = pre;
pre = curr;
curr = next;
}
return pre;
}
我的总结:
这段代码通过一系列精妙的指针操作,完美地实现了链表的部分反转。它首先引入一个虚拟头节点,优雅地统一了处理所有边界情况,特别是当需要从链表头部开始反转时。接着,它通过两次循环,精准地定位到了待反转区间的前驱节点、头节点和尾节点。在反转之前,它先切断了子链表与后续部分的连接,确保反转操作不会影响到链表的其他部分。然后,它调用一个标准的反转函数,将独立的子链表进行反转。最后,也是最关键的一步,它将反转后的子链表像搭积木一样,重新拼接到原链表中:前驱节点连接新的头节点,而原头节点(现在是新尾节点)则连接到之前保存的后续节点上。整个过程逻辑清晰,环环相扣,最终通过返回虚拟头节点的下一个节点,给出了正确的结果。这是一个非常经典和健壮的链表操作范例。