题目
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
解题思路一
穿针引线法:此方法只需遍历循环一次,即可完成。重点在于:找到left的开始节点的前一个节点:即pre节点,pre节点的下一个节点为curr(循环头节点),循环次数为right-left次,每次循环,用穿针引线的方式:第一步,记录curr的next节点;第二步,让curr的next指向next的下一个节点;第三步, 让next节点的next指向pre节点的下一个节点;第四步,让pre节点的next指向next节点即可
var reverseBetween = function(head, left, right) {
// 这里定义一个虚拟头节点
let virtual_node = new ListNode(-1);
virtual_node.next = head;
// 找到pre节点
let pre = virtual_node;
for (let i = 0; i < left - 1; i++) {
pre = pre.next;
}
// 穿针引线
let curr = pre.next;
for (let i = 0; i < right - left; i++) {
let next = curr.next;
curr.next = next.next;
next.next = pre.next;
pre.next = next;
}
return virtual_node.next;
};
解题思路二
常规方法:找到pre节点,找到反转节点的最右节点rightNode节点,将中间的链表取出反转,然后将pre的next指向反转后的rightNode节点,将leftNode(反转后的头部节点)的next指向rightNode截取之前的next节点
var reverseBetween = function(head, left, right) {
// 这里定义一个虚拟头节点
const virtualNode = new ListNode(-1);
virtualNode.next = head;
// 找到pre节点
let pre = virtualNode;
for (let i = 0; i < left - 1; i++) {
pre = pre.next;
}
找到反转节点的最右节点
let rightNode = pre;
for (let i = 0; i < right - left + 1; i++) {
rightNode = rightNode.next;
}
// 暂存反转前的最左节点和反转链表最右节点的下一个节点
let leftNode = pre.next;
let curr = rightNode.next;
// 切断链表获取需要反转的链表
pre.next = null;
rightNode.next = null;
// 反转链表
reverseList(leftNode);
// 接回到原来的链表中
pre.next = rightNode;
leftNode.next = curr;
return virtualNode.next;
};
const reverseList = (head) => {
let pre = null;
let cur = head;
while (cur) {
const next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
}