-
思路
-
一、判断长度是否大于K
- 是 =》 进行第二步
-
否 =》返回原链表hair.next
- ***注意:设计的虚拟头节点hair,无论翻转与否,hair.next会 始终指向原链表的头节点
-
二、翻转
-
2.1反转链表:myReverse(head, tail) { return [tail, head]}
- 核心代码同leetcode206题一致
-
2.2 子链表之家的头尾连接
-
子链表的头部与上一个子链表连接
-
出现一个问题——第一个子链表没有head之前的节点与之连接?? =》创建pre
- 代码: pre.next = head
-
-
子链表的尾部与下一个子链表连接
- 代码:tail.next = nex
-
-
2.3 翻转顺序
- 1、创建一个虚拟头节点
-
2、循环翻转子链表
-
1、确定第一组end/tail的位置
- let end = start
- end = end.next
-
2、用nex指针指着第二组的head
- const nex = end.next
- 3、调用myReverse(head, end)
-
4、首尾相连
- start.next = head
- tail.next = nex
-
5、更新start、head
- start = end
- head = nex
-
- 3、返回hair.next
-
- 代码展示
-
/**
* 反转 k 个一组的链表
* @param {ListNode} head - 链表的头节点
* @param {number} k - 每组的大小
* @return {ListNode}
*/
var reverseKGroup = function(head, k) {
// 定义反转函数 myReverse,接收头节点和尾节点,返回反转后的头尾节点
const myReverse = (head, end) => {
let prev = null;
let cur = head;
let temp = null
// 迭代反转链表
while (prev !== end) {
temp = cur.next; // 记录当前节点的下一个节点
cur.next = prev; // 将当前节点的 next 指向前一个节点
prev = cur; // 更新 prev 为当前节点
cur = temp; // 更新当前节点为原先记录的下一个节点
}
return [end, head]; // 返回反转后的头尾节点
}
const hair = new ListNode(0); // 创建一个虚拟头节点
hair.next = head; // 将虚拟头节点的 next 指向原链表头节点
let start = hair; // 初始化 start 为虚拟头节点
while (head) {
let end = start;
// 查看剩余部分长度是否大于等于 k
for (let i = 0; i < k; ++i) {
end = end.next; // 移动 end 指针
if (!end) {
return hair.next; // 剩余长度小于 k,直接返回原链表
}
}
const nex = end.next; // 记录反转区域的下一个节点
[head, end] = myReverse(head, end); // 反转当前 k 个节点
// 把子链表重新接回原链表
start.next = head; // 将虚拟头节点的 next 指向反转后的头节点
end.next = nex; // 反转后的尾节点指向反转区域的下一个节点
start = end; // 更新 start 为反转后的尾节点
head = nex; // 更新 head 为反转区域的下一个节点
}
return hair.next; // 返回虚拟头节点的 next,即反转后的链表头节点
};