「这是我参与11月更文挑战的第11天,活动详情查看:2021最后一次更文挑战」
题目:
92. 反转链表 II
给你单链表的头指针 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 <= 5001 <= left <= right <= n
进阶: 你可以使用一趟扫描完成反转吗?
思路:
- 为了避免判断是否从头部开始反转,给链表头部插入一个节点
result,result的下一个节点指向头节点; - 把链表拆成三段, 中间是要反转的数据, 头部和尾部不用做处理;
- 找到反转的起点
cur,让它停留在那个位置,找个代跑temp替它往后遍历。 然后对中间数据进行一个反转, 不懂如何反转整个链表的可以看一下我这篇文章 # [路飞]_一起刷leetcode 206. 反转链表; - 反转前记得记录中间数据的头节点
last,待会儿它反转后就是尾节点; - 反转完成。记录中间链表的头节点
prev, 和当前反转完成后,尾部头节点temp; - 让头部的末尾节点,链接中间的头节点,即:
cur.next = prev; - 让中间的末尾节点,链接尾部的头节点,即:
last.next = temp; - 返回我们插入的头节点的下一个节点
result.next就是我们要的答案。
实现:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @param {number} left
* @param {number} right
* @return {ListNode}
*/
var reverseBetween = function(head, left, right) {
// 如果要反转的片段是同个节点,那就不用转了
if (left === right) {
return head;
}
// 为了防止需要从头节点开始转,需要特殊处理, 所以在头节点前面插入一个元素
let result = new ListNode(0, head);
// 需要返回全部链表,所以需要找个代跑
let cur = result;
// 找到开始反转的节点
while (left > 1) {
cur = cur.next;
left--;
right--;
}
// 找个代跑。保留切割的位置。待会儿这个切割位next指向反转后的头节点
let temp = cur.next;
// 记录当前要反转的头节点,它是待会儿反转后的尾节点,链接尾部即可
let last = cur.next;
let prev = null;
// 反转中间的链表
while (right > 0) {
const next = temp.next;
temp.next = prev;
prev = temp;
temp = next;
right--;
}
// 反转结束,这时候把前半截和中间反转的这截链接
cur.next = prev;
// 中间反转的这截和尾部链接
last.next = temp;
return result.next;
};
看懂了的小伙伴可以点个关注、咱们下道题目见。如无意外以后文章都会以这种形式,有好的建议欢迎评论区留言。