LeetCode92 反转链表 II
题目
解题
解题一:穿针引线
// javascript
var reverseBetween = function(head, left, right) {
// 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
const dummyHead = new ListNode(0, head);
let prev = dummyHead;
// 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
// 建议写在 for 循环里,语义清晰
for (let i = 0; i < left - 1; i++) {
prev = prev.next;
}
// 第 2 步:从 prev 再走 right - left + 1 步,来到 right 节点
let rightNode = prev;
for (let i = 0; i < right - left + 1; i++) {
rightNode = rightNode.next;
}
// 第 3 步:切断出一个子链表(截取链表)
const leftNode = prev.next;
const nextNode = rightNode.next;
// 注意:切断链接
prev.next = null;
rightNode.next = null;
// 第 4 步:同第 206 题,反转链表的子区间
reverseList(leftNode);
// 第 5 步:接回到原来的链表中
prev.next = rightNode;
leftNode.next = nextNode;
return dummyHead.next;
};
const reverseList = (head) => {
let prev = null;
let cur = head;
while (cur !== null) {
const next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
};
解题二:一次遍历「穿针引线」反转链表(头插法)
为了节约时间,会一边遍历一边反转:反转链表 II
// javascript
var reverseBetween = function(head, left, right) {
const dummyHead = new ListNode(0, head);
let prev = dummyHead;
for (let i = 0; i < left - 1; ++i) {
prev = prev.next;
}
let cur = prev.next;
for (let i = 0; i < right - left; ++i) {
const next = cur.next;
cur.next = next.next;
next.next = prev.next;
prev.next = next;
}
return dummyHead.next;
};