题目描述

题目链接

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

进阶:

  • 你可以设计一个只使用常数额外空间的算法来解决此问题吗?
  • 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

算法1

(遍历一遍链表) $O(n)$

  • 创建 dummy 节点来保存头结点
  • k 个一组翻转链表:
    • 首先判断接下来是否有 k 个节点,如果没有的话直接退出
    • 类似于直接反转链表,两个一组,翻转即可,因此只需要翻转 k - 1
  • 翻转结束,处理一些边界
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {

auto dummy = new ListNode(-1);
dummy->next = head;
auto p = dummy;

for( ; p; )
{
auto q = p;
for(int i = 0; i < k && q; i ++) q = q->next;
if( !q) break;

auto a = p->next, b = a->next;
for(int i = 0; i < k - 1; i ++)
{
auto c = b->next;
b->next = a;
a = b;
b = c;
}

auto c = p->next;
p->next = a;
c->next = b;
p = c;
}

return dummy->next;
}
};

如果需要在反转结束后,将剩下的所有节点翻转呢?

(遍历一遍链表) $O(n)$

以 k 个一组反转之后,剩下的链表可以直接套用反转链表的代码来进行翻转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseKGroup(ListNode* head, int k) {

auto dummy = new ListNode(-1);
dummy->next = head;
auto p = dummy;

for( ; p; )
{
auto q = p;
for(int i = 0; i < k && q; i ++) q = q->next;
if( !q) break;

auto a = p->next, b = a->next;
for(int i = 0; i < k - 1; i ++)
{
auto c = b->next;
b->next = a;
a = b;
b = c;
}

auto c = p->next;
p->next = a;
c->next = b;
p = c;
}

// 翻转剩余的链表
auto t = p;
p = p->next;
auto q = p->next;
while( q)
{
auto a = q->next;
q->next = p;
p = q;
q = a;
}

t->next->next = NULL;
t->next = p;

return dummy->next;
}
};