@@ -163,221 +163,71 @@ func main() {
163
163
164
164
> 快慢指针最优解,不使用容器结构(stack),O(1):同样的找到中点位置,把右半部分指针回指到中点。接着指针1从L位置,指针2从R位置,往中间遍历。,每步比对,如果有不一样,则不是回文。返回答案之前,把中点右边的指针调整回来
165
165
166
- ``` Java
167
- package class06 ;
168
-
169
- import java.util.Stack ;
170
-
171
- public class Code02_IsPalindromeList {
172
-
173
- public static class Node {
174
- public int value;
175
- public Node next;
176
-
177
- public Node (int data ) {
178
- this . value = data;
179
- }
180
- }
181
-
182
- // need n extra space
183
- public static boolean isPalindrome1 (Node head ) {
184
- // 依次进栈
185
- Stack<Node > stack = new Stack<Node > ();
186
- Node cur = head;
187
- while (cur != null ) {
188
- stack. push(cur);
189
- cur = cur. next;
190
- }
191
- // 每个元素和栈中比较
192
- while (head != null ) {
193
- if (head. value != stack. pop(). value) {
194
- return false ;
195
- }
196
- head = head. next;
197
- }
198
- return true ;
199
- }
166
+ ``` Go
167
+ package main
200
168
201
- // need n/2 extra space
202
- // 中点右侧进栈
203
- public static boolean isPalindrome2 (Node head ) {
204
- if (head == null || head. next == null ) {
205
- return true ;
206
- }
207
- Node right = head. next;
208
- Node cur = head;
209
- while (cur. next != null && cur. next. next != null ) {
210
- right = right. next;
211
- cur = cur. next. next;
212
- }
213
- Stack<Node > stack = new Stack<Node > ();
214
- while (right != null ) {
215
- stack. push(right);
216
- right = right. next;
217
- }
218
- while (! stack. isEmpty()) {
219
- if (head. value != stack. pop(). value) {
220
- return false ;
221
- }
222
- head = head. next;
223
- }
224
- return true ;
225
- }
169
+ // 判断一个链表是否是回文链表
170
+ // 解法1:遍历链表,把链表放入一个数组中,倒序遍历数组切片,和正序遍历数组切片依次对比,都相等即为回文,实现略
171
+ // 解法2:遍历链表,按照快慢指针使慢指针定位到链表的中点位置,依次把慢指针指向的值写入数组切片中,此时数组中保存着链表前一半的元素。
172
+ // 且slow的位置是链表的中间位置。按倒序遍历数组切片,与按slow位置顺序遍历链表的元素依次对比,如果都相等,则为回文。实现略
173
+ // 解法2比解法1省了一半的空间,解法一空间复杂度O(n),解法2空间复杂度为O(n/2)
174
+ // 解法3:不使用额外空间,空间复杂度为O(1)
226
175
227
- // need O(1) extra space
228
- // 不使用容器(stack)的方法
229
- public static boolean isPalindrome3 (Node head ) {
230
- if (head == null || head. next == null ) {
231
- return true ;
232
- }
233
- // 慢指针
234
- Node n1 = head;
235
- // 快指针
236
- Node n2 = head;
237
- while (n2. next != null && n2. next. next != null ) { // find mid node
238
- n1 = n1. next; // n1 -> mid
239
- n2 = n2. next. next; // n2 -> end
240
- }
241
- // n1 中点
242
-
243
-
244
- n2 = n1. next; // n2 -> right part first node
245
- n1. next = null ; // mid.next -> null
246
- Node n3 = null ;
247
- // 右半部逆序指向中点
248
- while (n2 != null ) { // right part convert
249
- n3 = n2. next; // n3 -> save next node
250
- n2. next = n1; // next of right node convert
251
- n1 = n2; // n1 move
252
- n2 = n3; // n2 move
253
- }
254
- // 引入n3记录最后的位置,之后把右半部再逆序回原来的次序
255
- n3 = n1; // n3 -> save last node
256
- n2 = head;// n2 -> left first node
257
- boolean res = true ;
258
- while (n1 != null && n2 != null ) { // check palindrome
259
- if (n1. value != n2. value) {
260
- res = false ;
261
- break ;
262
- }
263
- n1 = n1. next; // left to mid
264
- n2 = n2. next; // right to mid
265
- }
266
- n1 = n3. next;
267
- n3. next = null ;
268
- // 把右半部分再逆序回来
269
- while (n1 != null ) { // recover list
270
- n2 = n1. next;
271
- n1. next = n3;
272
- n3 = n1;
273
- n1 = n2;
274
- }
275
- return res;
276
- }
176
+ type Node struct {
177
+ Val int
178
+ Next *Node
179
+ }
277
180
278
- public static void printLinkedList (Node node ) {
279
- System . out. print(" Linked List: " );
280
- while (node != null ) {
281
- System . out. print(node. value + " " );
282
- node = node. next;
283
- }
284
- System . out. println();
181
+ // IsPalindrome 给定链表头节点,判断该链表是不是回文链表。空间复杂度为O(1)
182
+ func (head *Node ) IsPalindrome () bool {
183
+ // 链表为空,或者链表只有一个节点,是回文结构
184
+ if head == nil || head.Next == nil {
185
+ return true
285
186
}
286
-
287
- public static void main (String [] args ) {
288
-
289
- Node head = null ;
290
- printLinkedList(head);
291
- System . out. print(isPalindrome1(head) + " | " );
292
- System . out. print(isPalindrome2(head) + " | " );
293
- System . out. println(isPalindrome3(head) + " | " );
294
- printLinkedList(head);
295
- System . out. println(" =========================" );
296
-
297
- head = new Node (1 );
298
- printLinkedList(head);
299
- System . out. print(isPalindrome1(head) + " | " );
300
- System . out. print(isPalindrome2(head) + " | " );
301
- System . out. println(isPalindrome3(head) + " | " );
302
- printLinkedList(head);
303
- System . out. println(" =========================" );
304
-
305
- head = new Node (1 );
306
- head. next = new Node (2 );
307
- printLinkedList(head);
308
- System . out. print(isPalindrome1(head) + " | " );
309
- System . out. print(isPalindrome2(head) + " | " );
310
- System . out. println(isPalindrome3(head) + " | " );
311
- printLinkedList(head);
312
- System . out. println(" =========================" );
313
-
314
- head = new Node (1 );
315
- head. next = new Node (1 );
316
- printLinkedList(head);
317
- System . out. print(isPalindrome1(head) + " | " );
318
- System . out. print(isPalindrome2(head) + " | " );
319
- System . out. println(isPalindrome3(head) + " | " );
320
- printLinkedList(head);
321
- System . out. println(" =========================" );
322
-
323
- head = new Node (1 );
324
- head. next = new Node (2 );
325
- head. next. next = new Node (3 );
326
- printLinkedList(head);
327
- System . out. print(isPalindrome1(head) + " | " );
328
- System . out. print(isPalindrome2(head) + " | " );
329
- System . out. println(isPalindrome3(head) + " | " );
330
- printLinkedList(head);
331
- System . out. println(" =========================" );
332
-
333
- head = new Node (1 );
334
- head. next = new Node (2 );
335
- head. next. next = new Node (1 );
336
- printLinkedList(head);
337
- System . out. print(isPalindrome1(head) + " | " );
338
- System . out. print(isPalindrome2(head) + " | " );
339
- System . out. println(isPalindrome3(head) + " | " );
340
- printLinkedList(head);
341
- System . out. println(" =========================" );
342
-
343
- head = new Node (1 );
344
- head. next = new Node (2 );
345
- head. next. next = new Node (3 );
346
- head. next. next. next = new Node (1 );
347
- printLinkedList(head);
348
- System . out. print(isPalindrome1(head) + " | " );
349
- System . out. print(isPalindrome2(head) + " | " );
350
- System . out. println(isPalindrome3(head) + " | " );
351
- printLinkedList(head);
352
- System . out. println(" =========================" );
353
-
354
- head = new Node (1 );
355
- head. next = new Node (2 );
356
- head. next. next = new Node (2 );
357
- head. next. next. next = new Node (1 );
358
- printLinkedList(head);
359
- System . out. print(isPalindrome1(head) + " | " );
360
- System . out. print(isPalindrome2(head) + " | " );
361
- System . out. println(isPalindrome3(head) + " | " );
362
- printLinkedList(head);
363
- System . out. println(" =========================" );
364
-
365
- head = new Node (1 );
366
- head. next = new Node (2 );
367
- head. next. next = new Node (3 );
368
- head. next. next. next = new Node (2 );
369
- head. next. next. next. next = new Node (1 );
370
- printLinkedList(head);
371
- System . out. print(isPalindrome1(head) + " | " );
372
- System . out. print(isPalindrome2(head) + " | " );
373
- System . out. println(isPalindrome3(head) + " | " );
374
- printLinkedList(head);
375
- System . out. println(" =========================" );
376
-
187
+ // 慢指针
188
+ slow := head
189
+ // 快指针
190
+ fast := head
191
+ for fast.Next != nil && fast.Next .Next != nil { // 循环结束,slow停在链表中点位置
192
+ slow = slow.Next
193
+ fast = fast.Next .Next
377
194
}
378
195
196
+ fast = slow.Next // 快指针回到中点的下一个节点,之后快指针将从每次走两步,变为每次走一步
197
+ slow.Next = nil // 从中点截断链表,mid.next -> nil
198
+ var tmp *Node
199
+ // 对原链表右半部分,进行逆序,逆序后,从原尾节点指向中点
200
+ for fast != nil {
201
+ tmp = fast.Next // tmp暂时保存fast的下一个节点
202
+ fast.Next = slow // 翻转链表指向
203
+ slow = fast // slow 移动
204
+ fast = tmp // fast 移动
205
+ }
206
+
207
+ // tmp指针记录最后的位置,之后把右半部再逆序回原来的次序
208
+ tmp = slow
209
+ fast = head
210
+ var res = true
211
+ for slow != nil && fast != nil { // 原链表的左右部门进行回文对比
212
+ if slow.Val != fast.Val {
213
+ res = false
214
+ break
215
+ }
216
+ slow = slow.Next // 从原链表头节点,往原链表中间节点移动
217
+ fast = fast.Next // 从原链表尾节点,往原链表中间节点移动
218
+ }
219
+ slow = tmp.Next
220
+ tmp.Next = nil
221
+ // 把原链表右半部分再逆序回来
222
+ for slow != nil {
223
+ fast = slow.Next
224
+ slow.Next = tmp
225
+ tmp = slow
226
+ slow = fast
227
+ }
228
+ // 返回回文的判断结果 true
229
+ return res
379
230
}
380
-
381
231
```
382
232
383
233
### 1.1.3 面试题二:按值划分单链表
0 commit comments