1 #include "000库函数.h"
2
3
4
5 struct ListNode {
6 int val;
7 ListNode *next;
8 ListNode(int x) : val(x), next(NULL) {}
9 };
10 /************************自己解答****************************/
11 //不含头结点,链表中的数据按照k个k个地翻转,使用栈进栈出原理
12 class Solution {
13 public:
14 ListNode* reverseKGroup(ListNode* head, int k) {
15 if (k <= 1 || !head || !(head->next))return head;
16 ListNode* Res = new ListNode(0);
17 ListNode* r = Res;
18 ListNode* p = head;
19 stack<int> S;
20 while (p) {
21 S.push(p->val);
22 p = p->next;
23 if (S.size() == k) {
24 while (!S.empty()) { //采用尾插法
25 ListNode* q = new ListNode(0);
26 q->val = S.top();
27 r->next = q;
28 r = q;
29 S.pop();
30 }
31 }
32 }
33 if (S.size()) {
34 while (!S.empty()) { //采用头插法
35 ListNode* q = new ListNode(0);
36 q->val = S.top();
37 q->next = r->next;
38 r->next = q;
39 S.pop();
40 }
41 }
42 return Res->next;
43
44 }
45
46 };
47
48
49
50
51 /*******************************博客答案***************************/
52 //这道题让我们以每k个为一组来翻转链表,实际上是把原链表分成若干小段,
53 //然后分别对其进行翻转,那么肯定总共需要两个函数,一个是用来分段的,
54 //一个是用来翻转的,我们就以题目中给的例子来看,对于给定链表1->2->3->4->5,
55 //一般在处理链表问题时,我们大多时候都会在开头再加一个dummy node,因为翻转链表时头结点可能会变化
56 //为了记录当前最新的头结点的位置而引入的dummy node,那么我们加入dummy node后的链表变为
57 //- 1->1->2->3->4->5,如果k为3的话,我们的目标是将1, 2, 3翻转一下,那么我们需要一些指针
58 //,pre和next分别指向要翻转的链表的前后的位置,然后翻转后pre的位置更新到如下新的位置:
59
60
61
62 //复制代码
63 //- 1->1->2->3->4->5
64 //| | |
65 //pre cur next
66 //
67 //- 1->3->2->1->4->5
68 //| | |
69 //cur pre next
70 //复制代码
71
72
73 //以此类推,只要cur走过k个节点,那么next就是cur->next,
74 //就可以调用翻转函数来进行局部翻转了,注意翻转之后新的cur和pre的位置都不同了,
75 //那么翻转之后,cur应该更新为pre->next,而如果不需要翻转的话,cur更新为cur->next,
76
77
78
79 //解法一://耗时超过自己的解答
80
81 class Solution {
82 public:
83 ListNode* reverseKGroup(ListNode* head, int k) {
84 if (!head || k == 1) return head;
85 ListNode *dummy = new ListNode(-1), *pre = dummy, *cur = head;
86 dummy->next = head;//添加头结点
87 for (int i = 1; cur; ++i) {
88 if (i % k == 0) {
89 pre = reverseOneGroup(pre, cur->next);
90 cur = pre->next;
91 }
92 else {
93 cur = cur->next;
94 }
95 }
96 return dummy->next;
97 }
98 ListNode* reverseOneGroup(ListNode* pre, ListNode* next) {
99 ListNode *last = pre->next, *cur = last->next;
100 while (cur != next) {
101 last->next = cur->next;
102 cur->next = pre->next;
103 pre->next = cur;
104 cur = last->next;
105 }
106 return last;
107 }
108 };
109
110
111
112 //我们也可以在一个函数中完成,我们首先遍历整个链表,统计出链表的长度,
113 //然后如果长度大于等于k,我们开始交换节点,当k = 2时,每段我们只需要交换一次,
114 //当k = 3时,每段需要交换2此,所以i从1开始循环,注意交换一段后更新pre指针,然后num自减k
115 //直到num < k时循环结束,参见代码如下:
116
117
118
119 //解法二:时间更长!!!!
120
121
122 class Solution {
123 public:
124 ListNode* reverseKGroup(ListNode* head, int k) {
125 ListNode *dummy = new ListNode(-1), *pre = dummy, *cur = pre;
126 dummy->next = head;
127 int num = 0;
128 while (cur = cur->next) ++num;
129 while (num >= k) {
130 cur = pre->next;
131 for (int i = 1; i < k; ++i) {
132 ListNode *t = cur->next;
133 cur->next = t->next;
134 t->next = pre->next;
135 pre->next = t;
136 }
137 pre = cur;
138 num -= k;
139 }
140 return dummy->next;
141 }
142 };
143
144
145
146 //我们也可以使用递归来做,我们用head记录每段的开始位置,cur记录结束位置的下一个节点,
147 //然后我们调用reverse函数来将这段翻转,然后得到一个new_head,原来的head就变成了末尾,
148 //这时候后面接上递归调用下一段得到的新节点,返回new_head即可,参见代码如下:
149
150
151 class Solution {
152 public:
153 ListNode* reverseKGroup(ListNode* head, int k) {
154 ListNode *cur = head;
155 for (int i = 0; i < k; ++i) {
156 if (!cur) return head;
157 cur = cur->next;
158 }
159 ListNode *new_head = reverse(head, cur);
160 head->next = reverseKGroup(cur, k);
161 return new_head;
162 }
163 ListNode* reverse(ListNode* head, ListNode* tail) {
164 ListNode *pre = tail;
165 while (head != tail) {
166 ListNode *t = head->next;
167 head->next = pre;
168 pre = head;
169 head = t;
170 }
171 return pre;
172 }
173 };
174
175
176 void T025() {
177 ListNode* N = new ListNode(0);
178 ListNode* p = N;
179 for (int i = 0; i < 5; ++i) {
180 ListNode* q = new ListNode(0);
181 q->val = i + 1;
182 p->next = q;
183 p = q;
184 }
185 p = N->next;
186 cout << "原:";
187 while (p) {
188 cout << p->val << ' ';
189 p = p->next;
190 }
191 cout << endl;
192 Solution S;
193 p = S.reverseKGroup(N->next,3);
194 cout << "转:";
195 while (p) {
196 cout << p->val << ' ';
197 p = p->next;
198 }
199 cout << endl;
200
201
202 }