「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
进阶:
- 你可以设计一个只使用常数额外空间的算法来解决此问题吗?
- 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
示例 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]
示例 4:
输入: head = [1], k = 1
输出: [1]
提示:
- 列表中节点的数量在范围
sz内 1 <= sz <= 50000 <= Node.val <= 10001 <= k <= sz
本题解题思路如下:
- 如果
k = 1,此时对每个节点为一组进行翻转,翻转后的链表和原链表是相同的,所以我们直接返回head即可 - 遍历链表,如果找到
k个节点,将它们为一组进行翻转,如果节点数量不够k个,返回head即可 - 递归的对剩余链表进行第二步操作,并将后续翻转后链表的头节点接在之前翻转后链表的尾结点后,直到遍历完整个链表
本题解题思路并不复杂,个人理解归类为困难难度主要因为操作链表的过程相对复杂一些,代码如下:
var reverseKGroup = function(head, k) {
// 特判
if(k===1) return head;
// 翻转函数
function reverse(head,k){
if(head === null || head.next === null) return head;
// 判断链表是否有K个节点
let pre = head,next = head.next,cnt = k;
while(cnt&&next){
cnt--;
// 将next的pre属性指向它的前一个节点,为后续翻转链表做准备
next.pre = pre;
pre = pre.next;
next = next.next;
}
// 不够K个节点,返回head
if(cnt) return head;
// 记录后续链表的头节点
const nextHead = next,
vhead = new ListNode(0);
next = pre,pre = head;
vhead.next = next;
// 翻转链表
while(next!==pre){
next.next = next.pre;
next = next.pre;
}
// 将后续链表的头节点接在翻转后链表的尾结点
next.next = reverse(nextHead,k)
// 返回翻转后链表的头节点
return vhead.next;
}
// 返回翻转后链表的头节点
return reverse(head,k-1);
};
至此我们就完成了 leetcode-25-K个一组翻转链表
如有任何问题或建议,欢迎留言讨论!