题目描述
题目链接
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。
k 是一个正整数,它的值小于或等于链表的长度。
如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。
进阶:
- 你可以设计一个只使用常数额外空间的算法来解决此问题吗?
- 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
算法1
(遍历一遍链表)  $O(n)$
- 创建 dummy节点来保存头结点
- k 个一组翻转链表:
- 首先判断接下来是否有 k 个节点,如果没有的话直接退出
- 类似于直接反转链表,两个一组,翻转即可,因此只需要翻转 k - 1次
 
- 翻转结束,处理一些边界
| 12
 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
 
 | 
 
 
 
 
 
 
 
 
 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 个一组反转之后,剩下的链表可以直接套用反转链表的代码来进行翻转
| 12
 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
 
 | 
 
 
 
 
 
 
 
 
 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;
 }
 };
 
 |