「这是我参与2022首次更文挑战的第14天,活动详情查看:2022首次更文挑战」
前言
死磕算法,每天至少完成一道算法题
今天咱们来做一下反转链表的升级版,昨天的反转链表想必大家都理解的七七八八了,今天咱们在突破一下这个中等题目(看到中等题目,大家要兴奋哦)
题目
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4 输出:[1,4,3,2,5]
思路
- 1.其中 left <= right,所以有可能left=right,这个咱们要判断的
分析
- 1.我们先自己画图,画图后就会发现,纯手工画图,哈哈😝
- 2.我们要反转的是2到4,但是我们反转后,1早忘了,所以我们先把1存储起来,(这里的诀窍就是把遍历过的节点,但是后面要改变指针的节点先保存起来)再看一下还有谁后面要改变指针,还有2,所以我们开始动手吧
我们先写框架
var reverseBetween = function(head, left, right) {
// 此处我们考虑一下left===right
if(!head||!head.next||left===right){
return head;
}
let dummy = new ListNode();
dummy.next = head;
// 声明要保存的节点
let pre,cur,leftHead,start;
return dummy.next;
};
接下来就是拿到leftHead,也就是左侧反转区间前的一个节点
// 定义一个哨兵,dummy代表着i=0;反转的时候都是从dummy开始的
let p = dummy.next;
// 因为是区间前面,所以left-1
for(let i=1;i<left-1;i++){
// 循环大家写了很多遍了,相信大家都会了
p = p.next;
}
leftHead = p;
再接下来我们保存反转区间的第一个元素,也就是leftHead.next
start = leftHead.next;
然后开始反转,反转如反转链表I的写法一样
pre = start;
cur = pre.next;
// 我们反转left到right区间内的数字
for(let i=left;i<right;i++){
let next = cur.next;
// 开始反转,当前节点的next指向前一个节点
cur.next = pre;
pre = cur;
cur = next;
}
此时的pre就是反转后的结果
// 改变1的指向
leftHead.next = pre;
// 改变start的指向,上面遍历结束以后,我们发现cur正好指向5,所以
start.next = cur;
题解
/**
* @param {ListNode} head
* @param {number} left
* @param {number} right
* @return {ListNode}
*/
var reverseBetween = function(head, left, right) {
// 此处我们考虑一下left===right
if(!head||!head.next||left===right){
return head;
}
let dummy = new ListNode();
dummy.next = head;
// 声明要保存的节点
let pre,cur,leftHead,start;
// 接下来就是拿到leftHead,也就是左侧反转区间前的一个节点
// 定义一个哨兵,dummy代表着i=0;反转的时候都是从dummy开始的
let p = dummy;
// 因为是区间前面,所以left-1
for(let i=0;i<left-1;i++){
// 循环大家写了很多遍了,相信大家都会了
p = p.next;
}
leftHead = p;
// 接下来我们保存反转区间的第一个元素,也就是leftHead.next
start = leftHead.next;
// 然后开始反转,反转如反转链表I的写法一样
pre = null;
cur = leftHead.next;
// 我们反转left到right区间内的数字
for(let i=left-1;i<right;i++){
let next = cur.next;
// 开始反转,当前节点的next指向前一个节点
cur.next = pre;
pre = cur;
cur = next;
}
// 改变1的指向
leftHead.next = pre;
// 改变start的指向,上面遍历结束以后,我们发现cur正好指向5,所以
start.next = cur;
return dummy.next;
};
总结
- 1.一定要先画图,真的链表题的诀窍就是先画图,一步步把结果画出来
- 2.我们遍历过得节点,如果后面用的到的话,那么先保存起来