大家好今天给大家分享下一道 LeetCode 困难难度 的题目[K 个一组翻转链表](leetcode-cn.com/problems/li…)
这里主要是分享思路和注释,供大家更好的理解题目解法,代码部分是参考LeetCode 转写成javascript 代码,
题目
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
示例1(图片转载LeetCode)
示例2(图片转载LeetCode)
示例1 输入:head = [1,2,3,4,5], k = 2 输出:[2,1,4,3,5] 示例2 输入:head = [1,2,3,4,5], k = 3 输出:[3,2,1,4,5] 示例3 输入:head = [1,2,3,4,5], k = 1 输出:[1,2,3,4,5]
分析
1.K是正整数
2.如果链表的长度不是k的整数倍 那么保留剩余节点的顺序
3.这道题和之前的两两交换相似,借鉴两两交换的思路设置dummy值
4.再利用之前学的翻转链表
解法
1.迭代
2.递归
解法一:迭代
代码借鉴 leetcode-cn.com/problems/re…
思路
1.先把链表分成k个元素一组
2.移动指针pre在 组的头部的上一个节点,指针end在组的尾部
3.翻转 组里面的元素
4.移动pre到下一个组的头部上一个节点,end 到下一个组的尾部
*/
var reverseKGroup = function (head, k) {
let dummy = new ListNode(0);
dummy.next = head;
//设置 2个指针 pre 和end
let pre = dummy;
let end = dummy;
while (end.next !== null) {
// 把end 移动到组的尾部
end = reachKNode(end, k);
// 如果有任何end等于undefined的情况 这说明,剩余的节点已经不够K个
// 直接结束循环
if (!end) break;
// 确定组中的开始节点和下一个组的开始节点
const start = pre.next;
const next = end.next;
// 断开组中最后一个节点的末尾,方便翻转链表
end.next = null;
// 翻转后start就变成了末尾
pre.next = reverse(start);
// 让start 指向下一个组的开始的节点
start.next = next;
// 把pre 和 end 指针指向翻转后的链表的最后一个节点,
// 为下次迭代做准备
pre = start;
end = pre;
}
return dummy.next;
//让end 到组的末尾
function reachKNode(node, k) {
while (k > 0) {
// 如果有等于零的就返回false
if (!node) {
return false;
}
node = node.next;
k--;
}
return node;
}
//翻转链表 迭代法
function reverse(node) {
let pre = null,
cur = node;
while (cur) {
let n = cur.next;
cur.next = pre;
// 移动指针
pre = cur;
cur = n;
}
return pre;
}
};
解法二:递归
思路
和迭代一样 只是reverse使用了递归的解法
var reverseKGroup = function (head, k) {
let dummy = new ListNode(0);
dummy.next = head;
//设置 2个指针 pre 和end
let pre = dummy;
let end = dummy;
while (end.next !== null) {
// 把end 移动到组的尾部
end = reachKNode(end, k);
// 如果有任何end等于undefined的情况 这说明,剩余的节点已经不够K个
// 直接结束循环
if (!end) break;
// 确定组中的开始节点和下一个组的开始节点
const start = pre.next;
const next = end.next;
// 断开组中最后一个节点的末尾,方便翻转链表
end.next = null;
// 翻转后start就变成了末尾
pre.next = reverse(start);
// 让start 指向下一个组的开始的节点
start.next = next;
// 把pre 和 end 指针指向翻转后的链表的最后一个节点,
// 为下次迭代做准备
pre = start;
end = pre;
}
return dummy.next;
//让end 到组的末尾
function reachKNode(node, k) {
while (k > 0) {
// 如果有等于零的就返回false
if (!node) {
return false;
}
node = node.next;
k--;
}
return node;
}
// 递归法
function reverse(node) {
if (!node || !node.next) {
return node;
}
const endNode = reverse(node.next);
node.next.next = node;
node.next = null;
return endNode;
}
};
总结
这道题是对之前的两两交换和翻转链表的一种综合考察,有兴趣的可以看看我专栏中分享的两两交换和翻转链表
大家可以看看我分享的一个专栏(前端搞算法)里面有更多关于算法的题目的分享,希望能够帮到大家,我会尽量保持每天晚上更新,如果喜欢的麻烦帮我点个赞,十分感谢
文章内容目的在于学习讨论与分享学习算法过程中的心得体会,文中部分素材来源网络,如有侵权,请联系删除,邮箱 182450609@qq.com