给你链表的头节点
head
,每k
**个节点一组进行翻转,请你返回修改后的链表。
k
是一个正整数,它的值小于或等于链表的长度。如果节点总数不是k
**的整数倍,那么请将最后剩余的节点保持原有顺序。你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
解法1 暴力解法
思路
暴力解法的思路其实和上一题一样,先把链表存在数组里,然后再进行 k
个一组的翻转,最后进行 next
指针的重置。
要注意如果后续链表长度不足 k
时应该保持原样。
代码
function reverseKGroup(head: ListNode | null, k: number): ListNode | null {
let cur = head;
const nodeList = [];
while (cur) {
nodeList.push(cur);
cur = cur.next;
}
let result = [];
let temp;
for (let i = 0; i < nodeList.length; i += k) {
temp = nodeList.slice(i, i + k);
if (temp.length === k) {
temp.reverse();
}
result = result.concat(temp);
}
for (let i = 0; i < result.length - 1; i++) {
result[i].next = result[i + 1];
}
result[result.length - 1].next = null;
return result[0];
};
时空复杂度
时间复杂度:经过了遍历,翻转以及链接操作,时间复杂度为 O(n)
空间复杂度:额外数组存储节点,O(n)
解法2 逐段翻转+链接
思路
k
个一组翻转可以看做翻转链表和链接新链表,我们把这一段直接进行翻转链表,然后这一段的头和尾的指针是不对的,没有链接到链表里去。我们再单独处理这一段就好了。
p0
的作用就是为了让翻转后的链表重新回到链表里去,初始化时是需要翻转的那一段链表的前一个节点。
代码
function reverseKGroup(head: ListNode | null, k: number): ListNode | null {
let n = 0;
let cur = head;
while (cur) {
n += 1;
cur = cur.next;
}
const dummyHead = new ListNode(-1, head);
let prev = null;
let p0 = dummyHead;
cur = head;
while (n >= k) {
n -= k;
for (let i = 0; i < k; i++) {
const next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
const nxt = p0.next;
p0.next.next = cur;
p0.next = prev;
p0 = nxt;
}
return dummyHead.next;
};
时空复杂度
时间复杂度:O(n)
空间复杂度:O(1)