-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathleetcode-list.html
866 lines (857 loc) · 361 KB
/
leetcode-list.html
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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
<!DOCTYPE html><html lang="zh-CN"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=2"><meta name="theme-color" content="#222"><meta http-equiv="X-UA-COMPATIBLE" content="IE=edge,chrome=1"><meta name="renderer" content="webkit"><link rel="icon" type="image/ico" sizes="32x32" href="/assets/favicon.ico"><link rel="apple-touch-icon" sizes="180x180" href="/assets/apple-touch-icon.png"><link rel="alternate" href="/rss.xml" title="Jiankychen's Blog" type="application/rss+xml"><link rel="alternate" href="/atom.xml" title="Jiankychen's Blog" type="application/atom+xml"><link rel="alternate" type="application/json" title="Jiankychen's Blog" href="https://jiankychen.github.io/feed.json"><link rel="preconnect" href="https://lf9-cdn-tos.bytecdntp.com"><link rel="preconnect" href="https://at.alicdn.com"><link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Mulish:400,400italic,700,700italic%7CFredericka%20the%20Great:400,400italic,700,700italic%7CNoto%20Serif%20JP:400,400italic,700,700italic%7CNoto%20Serif%20SC:400,400italic,700,700italic%7CInconsolata:400,400italic,700,700italic&display=swap&subset=latin,latin-ext" media="none" onload="this.media='all'"><link rel="stylesheet" href="/css/app.css?v=0.4.2"><link rel="modulepreload" href="/js/chunk-7IVLRIQ3.js"><link rel="modulepreload" href="/js/chunk-IXT6LZJL.js"><link rel="modulepreload" href="/js/chunk-PHSEV26P.js"><link rel="modulepreload" href="/js/chunk-XHQGHZCW.js"><link rel="modulepreload" href="/js/comments-TUWNDU5I.js"><link rel="modulepreload" href="/js/post-P6IN2S3Y.js"><link rel="modulepreload" href="/js/quicklink-HAJEHOPK.js"><link rel="modulepreload" href="/js/search-WFXK2K66.js"><link rel="modulepreload" href="/js/siteInit.js"><link rel="stylesheet" href="https://npm.webcache.cn/@waline/[email protected]/dist/waline.css" media="none" onload="this.media='all'"><link rel="preload" href="https://i.imgtg.com/2023/03/09/Y0xvg.jpg" as="image" fetchpriority="high"><link rel="preload" href="https://i.imgtg.com/2023/03/09/YSj7p.jpg" as="image" fetchpriority="high"><link rel="preload" href="https://img.timelessq.com/images/2022/07/26/99fb5ff897a82984470abf5e2a235d94.jpg" as="image" fetchpriority="high"><link rel="preload" href="https://img.timelessq.com/images/2022/07/26/9b626c5ba21d7cb4dbcba2b507688bbb.jpg" as="image" fetchpriority="high"><link rel="preload" href="https://img.timelessq.com/images/2022/07/26/488297bfd0233b6c6a444f1860e55d45.jpg" as="image" fetchpriority="high"><link rel="preload" href="https://img.timelessq.com/images/2022/07/26/65d0bfef68566882ce0560cab2e87921.jpg" as="image" fetchpriority="high"><meta name="keywords" content="链表"><link rel="canonical" href="https://jiankychen.github.io/leetcode-list"><title>LeetCode - 链表专题</title><meta name="generator" content="Hexo 7.0.0"></head><body itemscope="" itemtype="http://schema.org/WebPage"><div id="loading"><div class="cat"><div class="body"></div><div class="head"><div class="face"></div></div><div class="foot"><div class="tummy-end"></div><div class="bottom"></div><div class="legs left"></div><div class="legs right"></div></div><div class="paw"><div class="hands left"></div><div class="hands right"></div></div></div></div><div id="container"><header id="header" itemscope="" itemtype="http://schema.org/WPHeader"><div class="inner"><div id="brand"><div class="pjax"><h1 itemprop="name headline">LeetCode - 链表专题</h1><div class="meta"><span class="item" title="创建时间:2022-03-26 21:38:39"><span class="icon"><i class="ic i-calendar"></i></span><span class="text">发表于</span><time itemprop="dateCreated datePublished" datetime="2022-03-26T21:38:39+08:00">2022-03-26</time></span><span class="item" title="本文字数"><span class="icon"><i class="ic i-pen"></i></span><span class="text">本文字数</span><span>46k</span><span class="text">字</span></span><span class="item" title="阅读时长"><span class="icon"><i class="ic i-clock"></i></span><span class="text">阅读时长</span><span>42 分钟</span></span></div></div></div><nav id="nav"><div class="inner"><div class="toggle"><div class="lines" aria-label="切换导航栏"><span class="line"></span><span class="line"></span><span class="line"></span></div></div><ul class="menu"><li class="item title"><a href="/" rel="start">Jiankychen</a></li></ul><ul class="right" id="rightNav"><li class="item theme"><i class="ic i-sun"></i></li><li class="item search"><i class="ic i-search"></i></li></ul></div></nav></div><div class="pjax" id="imgs"><ul><li class="item" style="background-image: url("https://i.imgtg.com/2023/03/09/Y0xvg.jpg");"></li><li class="item" style="background-image: url("https://i.imgtg.com/2023/03/09/YSj7p.jpg");"></li><li class="item" style="background-image: url("https://img.timelessq.com/images/2022/07/26/99fb5ff897a82984470abf5e2a235d94.jpg");"></li><li class="item" style="background-image: url("https://img.timelessq.com/images/2022/07/26/9b626c5ba21d7cb4dbcba2b507688bbb.jpg");"></li><li class="item" style="background-image: url("https://img.timelessq.com/images/2022/07/26/488297bfd0233b6c6a444f1860e55d45.jpg");"></li><li class="item" style="background-image: url("https://img.timelessq.com/images/2022/07/26/65d0bfef68566882ce0560cab2e87921.jpg");"></li></ul></div></header><div id="waves"><svg class="waves" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 24 150 28" preserveAspectRatio="none" shape-rendering="auto"><defs><path id="gentle-wave" d="M-160 44c30 0 58-18 88-18s 58 18 88 18 58-18 88-18 58 18 88 18 v44h-352z"></path></defs><g class="parallax"><use xlink:href="#gentle-wave" x="48" y="0"></use><use xlink:href="#gentle-wave" x="48" y="3"></use><use xlink:href="#gentle-wave" x="48" y="5"></use><use xlink:href="#gentle-wave" x="48" y="7"></use></g></svg></div><main><div class="inner"><div class="pjax" id="main"><div class="article wrap"><div class="breadcrumb" itemlistelement="" itemscope="" itemtype="https://schema.org/BreadcrumbList"><i class="ic i-home"></i><span><a href="/">首页</a></span><i class="ic i-angle-right"></i><span class="current" itemprop="itemListElement" itemscope="itemscope" itemtype="https://schema.org/ListItem"><a href="/categories/Coding/" itemprop="item" rel="index" title="分类于Coding"><span itemprop="name">Coding<meta itemprop="position" content="0"></span></a></span></div><article class="post block" itemscope="itemscope" itemtype="http://schema.org/Article" lang="zh-CN"><link itemprop="mainEntityOfPage" href="https://jiankychen.github.io/leetcode-list.html"><span hidden="hidden" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person"><meta itemprop="image" content="/assets/avatar.jpg"><meta itemprop="name" content="Jiankychen"><meta itemprop="description" content="Never put off till tomorrow what you can do today, "></span><span hidden="hidden" itemprop="publisher" itemscope="itemscope" itemtype="http://schema.org/Organization"><meta itemprop="name" content="Jiankychen's Blog"></span><div class="body md" itemprop="articleBody"><h1 id="leetcode-2-两数相加"><a class="anchor" href="#leetcode-2-两数相加">#</a> LeetCode 2. 两数相加</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode.cn/problems/add-two-numbers/">LeetCode 2. Add Two Numbers</a></p>
<p>给你两个 <strong>非空</strong> 的链表,表示两个非负的整数。它们每位数字都是按照 <strong>逆序</strong> 的方式存储的,并且每个节点只能存储 <strong>一位</strong> 数字。</p>
<p>请你将两个数相加,并以相同形式返回一个表示和的链表。</p>
<p>你可以假设除了数字 0 之外,这两个数都不会以 0 开头。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode2_Example1.webp" alt=""></p>
<pre><code>输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
</code></pre>
<p><strong>示例 2:</strong></p>
<pre><code>输入:l1 = [0], l2 = [0]
输出:[0]
</code></pre>
<p><strong>示例 3:</strong></p>
<pre><code>输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li>每个链表中的节点数在范围 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>1</mn><mo separator="true">,</mo><mn>100</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[1, 100]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">100</span><span class="mclose">]</span></span></span></span> 内</li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>9</mn></mrow><annotation encoding="application/x-tex">\le 9</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">9</span></span></span></span></li>
<li>题目数据保证列表表示的数字不含前导零</li>
</ul>
<h2 id="思路"><a class="anchor" href="#思路">#</a> 思路</h2>
<p>链表的首端对应数的最低位,末端对应数的最高位</p>
<p>将两数相加,即,将两链表相同位置上的节点的值相加</p>
<p>注意,<strong>需要考虑进位</strong></p>
<ul>
<li>将来自前一位的进位值加到当前位</li>
<li>根据当前位的值,更新进位值</li>
<li>若最高位产生进位,则需新增一个更高位</li>
</ul>
<p>本题采用 模拟 算法来实现两数相加,即,模拟两数相加的计算过程(列竖式)</p>
<h2 id="method-模拟"><a class="anchor" href="#method-模拟">#</a> Method: 模拟</h2>
<h2 id="写法一"><a class="anchor" href="#写法一">#</a> 写法一</h2>
<p>将 <code>l1</code> 作为长链,并利用 <code>l1</code> 存储两数之和的结果</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">addTwoNumbers</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> l1<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> l2<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token keyword">int</span> num1 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">,</span> num2 <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span>ListNode <span class="token operator">*</span>cur1 <span class="token operator">=</span> l1<span class="token punctuation">;</span> cur1 <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> cur1 <span class="token operator">=</span> cur1<span class="token operator">-></span>next<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="4"></td><td><pre> num1<span class="token operator">++</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span>ListNode <span class="token operator">*</span>cur2 <span class="token operator">=</span> l2<span class="token punctuation">;</span> cur2 <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> cur2 <span class="token operator">=</span> cur2<span class="token operator">-></span>next<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="6"></td><td><pre> num2<span class="token operator">++</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>num1 <span class="token operator"><</span> num2<span class="token punctuation">)</span> <span class="token function">swap</span><span class="token punctuation">(</span>l1<span class="token punctuation">,</span> l2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 令 l1 指向长链</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token keyword">int</span> tag <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// 进位的值</span></pre></td></tr><tr><td data-num="9"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span>ListNode <span class="token operator">*</span>cur1 <span class="token operator">=</span> l1<span class="token punctuation">,</span> <span class="token operator">*</span>cur2 <span class="token operator">=</span> l2<span class="token punctuation">;</span> cur1 <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> cur1 <span class="token operator">=</span> cur1<span class="token operator">-></span>next<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>cur2<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//cur2 非空,应计算 cur1 、cur2 、 tag 之和</span></pre></td></tr><tr><td data-num="11"></td><td><pre> cur1<span class="token operator">-></span>val <span class="token operator">=</span> cur1<span class="token operator">-></span>val <span class="token operator">+</span> cur2<span class="token operator">-></span>val <span class="token operator">+</span> tag<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> cur2 <span class="token operator">=</span> cur2<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token comment">//cur2 为空,只计算 cur1 与 tag 之和</span></pre></td></tr><tr><td data-num="14"></td><td><pre> cur1<span class="token operator">-></span>val <span class="token operator">=</span> cur1<span class="token operator">-></span>val <span class="token operator">+</span> tag<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> tag <span class="token operator">=</span> cur1<span class="token operator">-></span>val <span class="token operator">/</span> <span class="token number">10</span><span class="token punctuation">;</span> <span class="token comment">// 更新进位值</span></pre></td></tr><tr><td data-num="16"></td><td><pre> cur1<span class="token operator">-></span>val <span class="token operator">%=</span> <span class="token number">10</span><span class="token punctuation">;</span> <span class="token comment">// 更新进位后的 cur1->val</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>cur1<span class="token operator">-></span>next <span class="token operator">&&</span> tag<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 最高位进 1</span></pre></td></tr><tr><td data-num="18"></td><td><pre> cur1<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span>tag<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="19"></td><td><pre> <span class="token keyword">return</span> l1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="20"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="21"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="22"></td><td><pre> <span class="token keyword">return</span> l1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="23"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>max</mi><mo></mo><mo stretchy="false">(</mo><mi>m</mi><mo separator="true">,</mo><mi>n</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\max(m, n))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mop">max</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mclose">))</span></span></span></span>,其中,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 分别为两链表的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<h2 id="写法二"><a class="anchor" href="#写法二">#</a> 写法二</h2>
<p>定义一个新的链表,存储计算结果</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">addTwoNumbers</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> l1<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> l2<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode <span class="token operator">*</span>head <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> <span class="token comment">//head 为结果链表的头节点</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode <span class="token operator">*</span>cur <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> <span class="token comment">//cur 为当前节点(通过 cur 将 head 链表串联起来)</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">int</span> carry <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// 进位</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>l1 <span class="token operator">||</span> l2<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token keyword">int</span> val1 <span class="token operator">=</span> l1 <span class="token operator">?</span> l1<span class="token operator">-></span>val <span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">,</span> val2 <span class="token operator">=</span> l2 <span class="token operator">?</span> l2<span class="token operator">-></span>val <span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">;</span> <span class="token comment">// 获取 l1 与 l2 节点的值</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token keyword">int</span> sum <span class="token operator">=</span> val1 <span class="token operator">+</span> val2 <span class="token operator">+</span> carry<span class="token punctuation">;</span> <span class="token comment">// 计算 l1 与 l2 节点值之和,再加上前一位的进位值</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>head <span class="token operator">==</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//head 为空,将两数之后的最低位值赋给 head</span></pre></td></tr><tr><td data-num="9"></td><td><pre> cur <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span>sum <span class="token operator">%</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> head <span class="token operator">=</span> cur<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="11"></td><td><pre> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">//head 不为空,令 cur 下一个节点的值为 sum % 10</span></pre></td></tr><tr><td data-num="12"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span>sum <span class="token operator">%</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="14"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="15"></td><td><pre> carry <span class="token operator">=</span> sum <span class="token operator">/</span> <span class="token number">10</span><span class="token punctuation">;</span> <span class="token comment">// 更新进位值</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>l1<span class="token punctuation">)</span> l1 <span class="token operator">=</span> l1<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">//l1 右移</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>l2<span class="token punctuation">)</span> l2 <span class="token operator">=</span> l2<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">//l2 右移</span></pre></td></tr><tr><td data-num="18"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="19"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>carry<span class="token punctuation">)</span> <span class="token comment">// 最高位的进位</span></pre></td></tr><tr><td data-num="20"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span>carry<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="21"></td><td><pre> <span class="token keyword">return</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="22"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>max</mi><mo></mo><mo stretchy="false">(</mo><mi>m</mi><mo separator="true">,</mo><mi>n</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\max(m, n))</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mop">max</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mclose">))</span></span></span></span>,其中,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 分别为两链表的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span>,这里未考虑存储结果所需的空间</p>
<p>参考:<a target="_blank" rel="noopener" href="https://leetcode.cn/problems/add-two-numbers/solution/liang-shu-xiang-jia-by-leetcode-solution/">力扣官方题解:两数相加</a></p>
<h1 id="leetcode-203-移除链表元素"><a class="anchor" href="#leetcode-203-移除链表元素">#</a> LeetCode 203. 移除链表元素</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/remove-linked-list-elements/">LeetCode 203. Remove Linked List Elements</a></p>
<p>给你一个链表的头节点 <code>head</code> 和一个整数 <code>val</code> ,请你删除链表中所有满足 <code>Node.val == val</code> 的节点,并返回 <strong>新的头节点</strong> 。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode203_1.webp" alt=""></p>
<pre><code>输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]
</code></pre>
<p><strong>示例 2:</strong></p>
<pre><code>输入:head = [], val = 1
输出:[]
</code></pre>
<p><strong>示例 3:</strong></p>
<pre><code>输入:head = [7,7,7,7], val = 7
输出:[]
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li>列表中的节点数目在范围 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[0, 10^4]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span> 内</li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">1 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>50</mn></mrow><annotation encoding="application/x-tex">\le 50</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">50</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>50</mn></mrow><annotation encoding="application/x-tex">\le 50</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">50</span></span></span></span></li>
</ul>
<h2 id="思路-2"><a class="anchor" href="#思路-2">#</a> 思路</h2>
<p>用 <code>cur</code> 表示当前节点:如果 <code>cur</code> 的下一个节点不为空 且 下一个节点的值等于给定的 <code>val</code> ,即, <code>cur->next != NULL && cur->next->val == val</code> ,则需要移除 <code>cur</code> 的下一个节点,即: <code>cur->next = cur->next->next</code></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode203_.webp" alt=""></p>
<p>但如果要移除的节点是头节点(它没有上个节点)怎么办?</p>
<ul>
<li>Method 1:直接将头节点向后移动</li>
<li>Method 2:在头节点前添加一个虚拟节点,使得原链表的所有节点均可按照常规的方式进行移除</li>
</ul>
<h2 id="method-1-直接使用原链表来进行删除操作"><a class="anchor" href="#method-1-直接使用原链表来进行删除操作">#</a> Method 1: 直接使用原链表来进行删除操作</h2>
<ol>
<li>
<p>若要移除头节点,只需将头节点向后移动一位</p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode203_3.webp" alt=""></p>
</li>
<li>
<p>考虑到新的头节点也可能是值为 <code>val</code> ,需要用循环来对头节点进行处理,直到头节点值不为 <code>val</code></p>
</li>
<li>
<p>对头节点以后的其他节点进行遍历,若需移除则按常规方式处理即可</p>
</li>
</ol>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">struct</span> <span class="token class-name">ListNode</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token keyword">int</span> val<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode <span class="token operator">*</span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token keyword">int</span> x<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token keyword">int</span> x<span class="token punctuation">,</span> ListNode <span class="token operator">*</span>next<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span>next<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="7"></td><td><pre><span class="token punctuation">}</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre></pre></td></tr><tr><td data-num="9"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">removeElements</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">,</span> <span class="token keyword">int</span> val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token comment">// 删除值为 val 的头节点</span></pre></td></tr><tr><td data-num="11"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>head <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> head<span class="token operator">-></span>val <span class="token operator">==</span> val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="12"></td><td><pre> ListNode<span class="token operator">*</span> tmp <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> head <span class="token operator">=</span> head<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="14"></td><td><pre> <span class="token keyword">delete</span> tmp<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="16"></td><td><pre></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token comment">// 删除值为 val 的非头节点</span></pre></td></tr><tr><td data-num="18"></td><td><pre> ListNode<span class="token operator">*</span> cur <span class="token operator">=</span> head<span class="token punctuation">;</span> <span class="token comment">// 遍历 cur 节点</span></pre></td></tr><tr><td data-num="19"></td><td><pre> <span class="token keyword">while</span><span class="token punctuation">(</span>cur <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> cur<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//cur 非空且 cur 的下一个节点非空</span></pre></td></tr><tr><td data-num="20"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>cur<span class="token operator">-></span>next<span class="token operator">-></span>val <span class="token operator">==</span> val<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 当 cur 的下一个节点的值为 val 时,删除 cur 的下一个节点</span></pre></td></tr><tr><td data-num="21"></td><td><pre> ListNode<span class="token operator">*</span> tmp <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="22"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="23"></td><td><pre> <span class="token keyword">delete</span> tmp<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="24"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="25"></td><td><pre> <span class="token keyword">else</span></pre></td></tr><tr><td data-num="26"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">//cur 向后移动</span></pre></td></tr><tr><td data-num="27"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="28"></td><td><pre></pre></td></tr><tr><td data-num="29"></td><td><pre> <span class="token comment">// 返回新的头节点</span></pre></td></tr><tr><td data-num="30"></td><td><pre> <span class="token keyword">return</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="31"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><blockquote>
<p>注意要从内存中删除移除的节点,清理节点内存</p>
</blockquote>
<h2 id="method-2-设置虚拟头节点再进行删除操作"><a class="anchor" href="#method-2-设置虚拟头节点再进行删除操作">#</a> Method 2: 设置虚拟头节点再进行删除操作</h2>
<p>设置一个虚拟头结点,原链表的所有节点便都可按照统一的方式进行移除</p>
<p>例如,给链表添加一个虚拟头结点为新的头结点,若要移除这个旧的头结点元素 1 时,只需将虚拟头节点的 <code>next</code> 指向旧的头节点的下一个节点,然后从内存中删除旧的头节点即可:<br>
<img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode203_4.webp" alt=""></p>
<p>注意,在 <code>return</code> 头节点 时, <code>return</code> 的应该是虚拟头节点的下一个节点,即, <code>return dummyHead->next;</code></p>
<p>最后也需要将添加的虚拟头节点 <code>dummyHead</code> 从内存中删掉</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">struct</span> <span class="token class-name">ListNode</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token keyword">int</span> val<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode <span class="token operator">*</span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token keyword">int</span> x<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token keyword">int</span> x<span class="token punctuation">,</span> ListNode <span class="token operator">*</span>next<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span>next<span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="7"></td><td><pre><span class="token punctuation">}</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre></pre></td></tr><tr><td data-num="9"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">removeElements</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">,</span> <span class="token keyword">int</span> val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token comment">// 设置虚拟头节点</span></pre></td></tr><tr><td data-num="11"></td><td><pre> ListNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 创建虚拟头节点</span></pre></td></tr><tr><td data-num="12"></td><td><pre> dummyHead<span class="token operator">-></span>next <span class="token operator">=</span> head<span class="token punctuation">;</span> <span class="token comment">// 令虚拟头节点指向 head</span></pre></td></tr><tr><td data-num="13"></td><td><pre></pre></td></tr><tr><td data-num="14"></td><td><pre> <span class="token comment">// 移除操作</span></pre></td></tr><tr><td data-num="15"></td><td><pre> ListNode<span class="token operator">*</span> cur <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>cur<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>cur<span class="token operator">-></span>next<span class="token operator">-></span>val <span class="token operator">==</span> val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="18"></td><td><pre> ListNode<span class="token operator">*</span> tmp <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="19"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="20"></td><td><pre> <span class="token keyword">delete</span> tmp<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="21"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="22"></td><td><pre> <span class="token keyword">else</span></pre></td></tr><tr><td data-num="23"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="24"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="25"></td><td><pre></pre></td></tr><tr><td data-num="26"></td><td><pre> <span class="token comment">// 返回虚拟头节点的下个节点,并删除虚拟头节点</span></pre></td></tr><tr><td data-num="27"></td><td><pre> head <span class="token operator">=</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="28"></td><td><pre> <span class="token keyword">delete</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="29"></td><td><pre> <span class="token keyword">return</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="30"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,其中,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 是链表的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<h1 id="leetcode-707-设计链表"><a class="anchor" href="#leetcode-707-设计链表">#</a> LeetCode 707. 设计链表</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/design-linked-list/">LeetCode 707. Design Linked List</a></p>
<p>你可以选择使用单链表或者双链表,设计并实现自己的链表。</p>
<p>单链表中的节点应该具备两个属性: <code>val</code> 和 <code>next</code> 。 <code>val</code> 是当前节点的值, <code>next</code> 是指向下一个节点的指针 / 引用。</p>
<p>如果是双向链表,则还需要属性 <code>prev</code> 以指示链表中的上一个节点。假设链表中的所有节点下标从 <code>0</code> 开始。</p>
<p>实现 <code>MyLinkedList</code> 类:</p>
<ul>
<li><code>MyLinkedList()</code> 初始化 <code>MyLinkedList</code> 对象。</li>
<li><code>int get(int index)</code> 获取链表中下标为 <code>index</code> 的节点的值。如果下标无效,则返回 <code>-1</code> 。</li>
<li><code>void addAtHead(int val)</code> 将一个值为 <code>val</code> 的节点插入到链表中第一个元素之前。在插入完成后,新节点会成为链表的第一个节点。</li>
<li><code>void addAtTail(int val)</code> 将一个值为 <code>val</code> 的节点追加到链表中作为链表的最后一个元素。</li>
<li><code>void addAtIndex(int index, int val)</code> 将一个值为 <code>val</code> 的节点插入到链表中下标为 <code>index</code> 的节点之前。如果 <code>index</code> 等于链表的长度,那么该节点会被追加到链表的末尾。如果 <code>index</code> 比长度更大,该节点将 不会插入 到链表中。</li>
<li><code>void deleteAtIndex(int index)</code> 如果下标有效,则删除链表中下标为 <code>index</code> 的节点。</li>
</ul>
<p><strong>示例 1:</strong></p>
<pre><code>输入:
["MyLinkedList", "addAtHead", "addAtTail", "addAtIndex", "get", "deleteAtIndex", "get"]
[[], [1], [3], [1, 2], [1], [1], [1]]
输出:
[null, null, null, null, 2, null, 3]
解释:
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.addAtHead(1);
myLinkedList.addAtTail(3);
myLinkedList.addAtIndex(1, 2); // 链表变为 1->2->3
myLinkedList.get(1); // 返回 2
myLinkedList.deleteAtIndex(1); // 现在,链表变为 1->3
myLinkedList.get(1); // 返回 3
</code></pre>
<p></p>
<p><strong>提示:</strong></p>
<ul>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>index</code> , <code>val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>1000</mn></mrow><annotation encoding="application/x-tex">\le 1000</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">1000</span></span></span></span></li>
<li>请不要使用内置的 LinkedList 库</li>
<li>调用 <code>get</code> 、 <code>addAtHead</code> 、 <code>addAtTail</code> 、 <code>addAtIndex</code> 和 <code>deleteAtIndex</code> 的次数不超过 2000</li>
</ul>
<h2 id="思路-3"><a class="anchor" href="#思路-3">#</a> 思路</h2>
<p>旨在设计链表的五个接口,以实现链表的常见操作:</p>
<ul>
<li>获取链表第 <code>index</code> 个节点的数值</li>
<li>在链表的最前面插入一个节点</li>
<li>在链表的最后面插入一个节点</li>
<li>在链表第 <code>index</code> 个节点前面插入一个节点</li>
<li>删除链表的第 <code>index</code> 个节点</li>
</ul>
<p>链表操作的两种方式:</p>
<ul>
<li>直接使用原来的链表来进行操作</li>
<li>设置一个虚拟头结点再进行操作</li>
</ul>
<h2 id="method-单链表"><a class="anchor" href="#method-单链表">#</a> Method: 单链表</h2>
<p>接下来以设计单链表的五个接口为例,采用设置虚拟头节点的方式执行相关操作</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token comment">// 定义链表的结构体</span></pre></td></tr><tr><td data-num="2"></td><td><pre><span class="token keyword">struct</span> <span class="token class-name">LinkedNode</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="3"></td><td><pre> <span class="token keyword">int</span> val<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> LinkedNode <span class="token operator">*</span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token function">LinkedNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token function">LinkedNode</span><span class="token punctuation">(</span><span class="token keyword">int</span> x<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">val</span><span class="token punctuation">(</span>x<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="7"></td><td><pre><span class="token punctuation">}</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre></pre></td></tr><tr><td data-num="9"></td><td><pre><span class="token keyword">class</span> <span class="token class-name">MyLinkedList</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="10"></td><td><pre></pre></td></tr><tr><td data-num="11"></td><td><pre> LinkedNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">LinkedNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> <span class="token keyword">int</span> size<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre></pre></td></tr><tr><td data-num="14"></td><td><pre><span class="token keyword">public</span><span class="token operator">:</span></pre></td></tr><tr><td data-num="15"></td><td><pre></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token comment">// 初始化链表</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token function">MyLinkedList</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="18"></td><td><pre> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">LinkedNode</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 虚拟头节点</span></pre></td></tr><tr><td data-num="19"></td><td><pre> size <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="20"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="21"></td><td><pre> </pre></td></tr><tr><td data-num="22"></td><td><pre> <span class="token comment">// 获取链表第 index 个节点的值</span></pre></td></tr><tr><td data-num="23"></td><td><pre> <span class="token keyword">int</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token keyword">int</span> index<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="24"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token generic-function"><span class="token function">index</span> <span class="token generic class-name"><span class="token operator"><</span> <span class="token number">0</span> <span class="token operator">||</span> index <span class="token operator">></span></span></span> <span class="token punctuation">(</span>size <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="25"></td><td><pre> <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="26"></td><td><pre> LinkedNode<span class="token operator">*</span> cur <span class="token operator">=</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="27"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>index<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 循环结束时 cur 指向第 index 个节点</span></pre></td></tr><tr><td data-num="28"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="29"></td><td><pre> index<span class="token operator">--</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="30"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="31"></td><td><pre> <span class="token keyword">return</span> cur<span class="token operator">-></span>val<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="32"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="33"></td><td><pre> </pre></td></tr><tr><td data-num="34"></td><td><pre> <span class="token comment">// 在链表的第一个元素之前插入值为 val 的节点,注意要更新链表长度</span></pre></td></tr><tr><td data-num="35"></td><td><pre> <span class="token keyword">void</span> <span class="token function">addAtHead</span><span class="token punctuation">(</span><span class="token keyword">int</span> val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="36"></td><td><pre> LinkedNode<span class="token operator">*</span> newHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">LinkedNode</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="37"></td><td><pre> newHead<span class="token operator">-></span>next <span class="token operator">=</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="38"></td><td><pre> dummyHead<span class="token operator">-></span>next <span class="token operator">=</span> newHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="39"></td><td><pre> size<span class="token operator">++</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="40"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="41"></td><td><pre> </pre></td></tr><tr><td data-num="42"></td><td><pre> <span class="token comment">// 在链表的末尾添加值为 val 的节点,注意要更新链表长度</span></pre></td></tr><tr><td data-num="43"></td><td><pre> <span class="token keyword">void</span> <span class="token function">addAtTail</span><span class="token punctuation">(</span><span class="token keyword">int</span> val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="44"></td><td><pre> LinkedNode<span class="token operator">*</span> cur <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="45"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>cur<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="46"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="47"></td><td><pre> LinkedNode<span class="token operator">*</span> newTail <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">LinkedNode</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="48"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> newTail<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="49"></td><td><pre> size<span class="token operator">++</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="50"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="51"></td><td><pre> </pre></td></tr><tr><td data-num="52"></td><td><pre> <span class="token comment">// 在链表中的第 index 个节点之前添加值为 val 的节点,注意要更新链表长度</span></pre></td></tr><tr><td data-num="53"></td><td><pre> <span class="token keyword">void</span> <span class="token function">addAtIndex</span><span class="token punctuation">(</span><span class="token keyword">int</span> index<span class="token punctuation">,</span> <span class="token keyword">int</span> val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="54"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator">></span> size<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="55"></td><td><pre> <span class="token keyword">return</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="56"></td><td><pre> LinkedNode<span class="token operator">*</span> cur <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="57"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>index<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 循环结束时 cur 指向第 index - 1 个节点</span></pre></td></tr><tr><td data-num="58"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="59"></td><td><pre> index<span class="token operator">--</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="60"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="61"></td><td><pre> LinkedNode<span class="token operator">*</span> newNode <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">LinkedNode</span><span class="token punctuation">(</span>val<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="62"></td><td><pre> newNode<span class="token operator">-></span>next <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="63"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> newNode<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="64"></td><td><pre> size<span class="token operator">++</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="65"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="66"></td><td><pre></pre></td></tr><tr><td data-num="67"></td><td><pre> <span class="token comment">// 删除第 index 个节点,注意要更新链表长度</span></pre></td></tr><tr><td data-num="68"></td><td><pre> <span class="token keyword">void</span> <span class="token function">deleteAtIndex</span><span class="token punctuation">(</span><span class="token keyword">int</span> index<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="69"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>index <span class="token operator"><</span> <span class="token number">0</span> <span class="token operator">||</span> index <span class="token operator">>=</span> size<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="70"></td><td><pre> <span class="token keyword">return</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="71"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="72"></td><td><pre> LinkedNode<span class="token operator">*</span> cur <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="73"></td><td><pre> <span class="token keyword">while</span><span class="token punctuation">(</span>index<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 循环结束时 cur 指向第 index - 1 个节点</span></pre></td></tr><tr><td data-num="74"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="75"></td><td><pre> index<span class="token operator">--</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="76"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="77"></td><td><pre> LinkedNode<span class="token operator">*</span> tmp <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="78"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="79"></td><td><pre> <span class="token keyword">delete</span> tmp<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="80"></td><td><pre> size<span class="token operator">--</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="81"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="82"></td><td><pre><span class="token punctuation">}</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="83"></td><td><pre></pre></td></tr><tr><td data-num="84"></td><td><pre><span class="token comment">/**</span></pre></td></tr><tr><td data-num="85"></td><td><pre> * Your MyLinkedList object will be instantiated and called as such:</pre></td></tr><tr><td data-num="86"></td><td><pre> * MyLinkedList* obj = new MyLinkedList();</pre></td></tr><tr><td data-num="87"></td><td><pre> * int param_1 = obj->get(index);</pre></td></tr><tr><td data-num="88"></td><td><pre> * obj->addAtHead(val);</pre></td></tr><tr><td data-num="89"></td><td><pre> * obj->addAtTail(val);</pre></td></tr><tr><td data-num="90"></td><td><pre> * obj->addAtIndex(index,val);</pre></td></tr><tr><td data-num="91"></td><td><pre> * obj->deleteAtIndex(index);</pre></td></tr><tr><td data-num="92"></td><td><pre> */</pre></td></tr></tbody></table></figure><h1 id="leetcode-876-链表的中间结点"><a class="anchor" href="#leetcode-876-链表的中间结点">#</a> LeetCode 876. 链表的中间结点</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/middle-of-the-linked-list/">LeetCode 876. Middle of the Linked List</a></p>
<p>给你单链表的头结点 <code>head</code> ,请你找出并返回链表的中间结点。</p>
<p>如果有两个中间结点,则返回第二个中间结点。</p>
<p><strong>示例 1:</strong></p>
<pre><code>输入:head = [1,2,3,4,5]
输出:[3,4,5]
解释:链表只有一个中间结点,值为 3
</code></pre>
<p><strong>示例 2:</strong></p>
<pre><code>输入:head = [1,2,3,4,5,6]
输出:[4,5,6]
解释:该链表有两个中间结点,值分别为 3 和 4 ,返回第二个结点
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li>链表的结点数范围是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>1</mn><mo separator="true">,</mo><mn>100</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[1, 100]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">100</span><span class="mclose">]</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">1 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>100</mn></mrow><annotation encoding="application/x-tex">\le 100</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">100</span></span></span></span></li>
</ul>
<h2 id="method-1-数组"><a class="anchor" href="#method-1-数组">#</a> Method 1: 数组</h2>
<p>对链表进行遍历,同时将遍历到的元素依次放入数组 <code>A</code> 中。如果我们遍历到了 <code>N</code> 个元素,那么链表以及数组的长度也为 <code>N</code> ,对应的中间节点即为 <code>A[N/2]</code></p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">middleNode</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> vector<span class="token operator"><</span>ListNode<span class="token operator">*</span><span class="token operator">></span> A <span class="token operator">=</span> <span class="token punctuation">{</span>head<span class="token punctuation">}</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>A<span class="token punctuation">.</span><span class="token function">back</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="4"></td><td><pre> A<span class="token punctuation">.</span><span class="token function">push_back</span><span class="token punctuation">(</span>A<span class="token punctuation">.</span><span class="token function">back</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">-></span>next<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">return</span> A<span class="token punctuation">[</span>A<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">]</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,其中 <code>N</code> 是给定链表中的结点数目。</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,即数组 <code>A</code> 用去的空间。</p>
<h2 id="method-2-单指针"><a class="anchor" href="#method-2-单指针">#</a> Method 2: 单指针</h2>
<p>对链表进行两次遍历。第一次遍历时,我们统计链表中的元素个数 <code>N</code> ;第二次遍历时,我们遍历到第 <code>N/2</code> 个元素(链表的首节点为第 <code>0</code> 个元素)时,将该元素返回即可</p>
<blockquote>
<p>注意,题目要求「两个中间结点的时候,返回<strong>第二个中间结点</strong>」。此时,快指针可以前进的条件是:<strong>当前快指针和当前快指针的下一个结点都非空</strong>。</p>
<p>如果题目要求「在两个中间结点的时候,返回<strong>第一个中间结点</strong>」,快指针可以前进的条件是:<strong>当前快指针的下一个结点和当前快指针的下下一个结点都非空</strong>。</p>
</blockquote>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">middleNode</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode <span class="token operator">*</span>current <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> <span class="token keyword">int</span> n <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>current <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token comment">// 统计链表的节点数</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="6"></td><td><pre> n<span class="token operator">++</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> current <span class="token operator">=</span> current<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="9"></td><td><pre> current <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> n <span class="token operator">/</span> <span class="token number">2</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token comment">// 寻找链表的中间节点</span></pre></td></tr><tr><td data-num="11"></td><td><pre> current <span class="token operator">=</span> current<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> <span class="token keyword">return</span> current<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,其中 <code>N</code> 是给定链表的结点数目</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span>,只需要常数空间存放变量和指针</p>
<h2 id="method-3-快慢指针"><a class="anchor" href="#method-3-快慢指针">#</a> Method 3: 快慢指针</h2>
<p>用两个指针 <code>slow</code> 与 <code>fast</code> 一起遍历链表。 <code>slow</code> 一次走一步, <code>fast</code> 一次走两步。那么当 <code>fast</code> 到达链表的末尾时, <code>slow</code> 必然位于中间</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">middleNode</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token comment">// 快慢指针,快指针一次前进两步,慢指针一次前进一步</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode <span class="token operator">*</span>fast <span class="token operator">=</span> head<span class="token punctuation">,</span> <span class="token operator">*</span>slow <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token comment">// 判断条件为:快指针当前节点非空且下一节点都非空。这样才能保证返回第二个中间节点(存在两个中间节点时)</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>fast <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> fast<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> </pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="7"></td><td><pre> slow <span class="token operator">=</span> slow<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre> fast <span class="token operator">=</span> fast<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="9"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token keyword">return</span> slow<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="11"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,其中 <code>N</code> 是给定链表的结点数目。</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span>,只需要常数空间存放 <code>slow</code> 和 <code>fast</code> 两个指针。</p>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/middle-of-the-linked-list/solution/lian-biao-de-zhong-jian-jie-dian-by-leetcode-solut/">题解:链表的中间结点</a></p>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/middle-of-the-linked-list/solution/kuai-man-zhi-zhen-zhu-yao-zai-yu-diao-shi-by-liwei/">题解:快慢指针(注意链表长度为偶数时,返回第 2 个结点的细节)</a></p>
<h1 id="leetcode-206-反转链表"><a class="anchor" href="#leetcode-206-反转链表">#</a> LeetCode 206. 反转链表</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/reverse-linked-list/">LeetCode 206. Reverse Linked List</a></p>
<p>给你单链表的头节点 <code>head</code> ,请你反转链表,并返回反转后的链表。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode206_1.webp" alt=""></p>
<pre><code>输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]
</code></pre>
<p><strong>示例 2:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode206_2.webp" alt=""></p>
<pre><code>输入:head = [1,2]
输出:[2,1]
</code></pre>
<p><strong>示例 3:</strong></p>
<pre><code>输入:head = []
输出:[]
</code></pre>
<p></p>
<p><strong>提示:</strong></p>
<ul>
<li>链表中节点的数目范围是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>0</mn><mo separator="true">,</mo><mn>5000</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[0, 5000]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">5000</span><span class="mclose">]</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>−</mo><mn>5000</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">- 5000 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">−</span><span class="mord">5000</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>5000</mn></mrow><annotation encoding="application/x-tex">\le 5000</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">5000</span></span></span></span></li>
</ul>
<p><strong>进阶</strong>:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?</p>
<h2 id="method-1-双指针"><a class="anchor" href="#method-1-双指针">#</a> Method 1: 双指针</h2>
<p>要实现链表的反转,只需改变链表节点 <code>next</code> 指针的指向</p>
<p>算法流程:</p>
<ol>
<li>定义 <code>cur</code> 指向当前处理节点,初始指向头节点;定义 <code>pre</code> 指向 <code>cur</code> 的上一个节点,初始化为 <code>NULL</code></li>
<li>遍历 <code>cur</code> ,直到 <code>cur</code> 为空
<ul>
<li>存储 <code>cur</code> 的下一个节点指针(因为接下来要改变 <code>cur->next</code> ),记作 <code>tmp = cur->next</code></li>
<li>修改 <code>cur</code> 的 <code>next</code> 指针的指向,令其指向上一个节点 <code>pre</code> ,即, <code>cur->next = pre</code> ,实现反转</li>
<li><code>pre</code> 和 <code>cur</code> 同时向后移动:执行 <code>pre = cur</code> , <code>cur = tmp</code></li>
</ul>
</li>
<li>遍历结束时, <code>pre</code> 指向的是原链表的最后一个节点,同时也是反转之后新链表的头节点,因此,返回 <code>pre</code> 即可</li>
</ol>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">reverseList</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode<span class="token operator">*</span> temp<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> pre <span class="token operator">=</span> <span class="token constant">NULL</span><span class="token punctuation">;</span> <span class="token comment">// 前置节点</span></pre></td></tr><tr><td data-num="4"></td><td><pre> ListNode<span class="token operator">*</span> cur <span class="token operator">=</span> head<span class="token punctuation">;</span> <span class="token comment">// 当前处理节点</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">while</span><span class="token punctuation">(</span>cur<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="6"></td><td><pre> temp <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">// 保存 cur 的下一个节点</span></pre></td></tr><tr><td data-num="7"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> pre<span class="token punctuation">;</span> <span class="token comment">// 反转</span></pre></td></tr><tr><td data-num="8"></td><td><pre> pre <span class="token operator">=</span> cur<span class="token punctuation">;</span> <span class="token comment">// 更新 pre 指针</span></pre></td></tr><tr><td data-num="9"></td><td><pre> cur <span class="token operator">=</span> temp<span class="token punctuation">;</span> <span class="token comment">// 更新 cur 指针</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="11"></td><td><pre> <span class="token keyword">return</span> pre<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 为链表长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<h2 id="method-2-递归"><a class="anchor" href="#method-2-递归">#</a> Method 2: 递归</h2>
<p>可以利用递归算法实现上述双指针算法的逻辑,代码如下:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">reverse</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> pre<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> cur<span class="token punctuation">)</span><span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token keyword">if</span><span class="token punctuation">(</span>cur <span class="token operator">==</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token keyword">return</span> pre<span class="token punctuation">;</span> <span class="token comment">// 递归终止条件,返回的是反转链表的头节点</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> temp <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> pre<span class="token punctuation">;</span> <span class="token comment">// 修改 cur 的 next 指针,指向 pre</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">return</span> <span class="token function">reverse</span><span class="token punctuation">(</span>cur<span class="token punctuation">,</span>temp<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 递归,使 temp 的 next 指针指向 cur</span></pre></td></tr><tr><td data-num="6"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="7"></td><td><pre></pre></td></tr><tr><td data-num="8"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">reverseList</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="9"></td><td><pre> <span class="token keyword">return</span> <span class="token function">reverse</span><span class="token punctuation">(</span><span class="token constant">NULL</span><span class="token punctuation">,</span> head<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>上述算法实质上都是沿着链表的方向 <strong>从前往后</strong> 翻转指针指向</p>
<p>也可以 <strong>从后往前</strong> 翻转 next 指针的指向</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">reverseList</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 翻转 head->next 的 next 指针,使其指向 head</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>head <span class="token operator">||</span> <span class="token operator">!</span>head<span class="token operator">-></span>next<span class="token punctuation">)</span> <span class="token keyword">return</span> head<span class="token punctuation">;</span> <span class="token comment">// 递归终止条件</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> newHead <span class="token operator">=</span> <span class="token function">reverseList</span><span class="token punctuation">(</span>head<span class="token operator">-></span>next<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 递归,使 head->next->next 的下一个节点变为 head->next</span></pre></td></tr><tr><td data-num="4"></td><td><pre> head<span class="token operator">-></span>next<span class="token operator">-></span>next <span class="token operator">=</span> head<span class="token punctuation">;</span> <span class="token comment">// 使 head->next 的下一个节点变为 head</span></pre></td></tr><tr><td data-num="5"></td><td><pre> head<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> <span class="token comment">// 此时的 head 节点为反转链表的尾节点,next 指针应为空指针</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token keyword">return</span> newHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 为链表长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,递归调用的栈空间</p>
<p>参考:<a target="_blank" rel="noopener" href="https://www.programmercarl.com/0206.%E7%BF%BB%E8%BD%AC%E9%93%BE%E8%A1%A8.html">代码随想录:翻转链表</a></p>
<h1 id="leetcode-24-两两交换链表中的节点"><a class="anchor" href="#leetcode-24-两两交换链表中的节点">#</a> LeetCode 24. 两两交换链表中的节点</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/swap-nodes-in-pairs/">LeetCode 24. Swap Nodes in Pairs</a></p>
<p>给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode24_Example1.webp" alt=""></p>
<pre><code>输入:head = [1,2,3,4]
输出:[2,1,4,3]
</code></pre>
<p><strong>示例 2:</strong></p>
<pre><code>输入:head = []
输出:[]
</code></pre>
<p><strong>示例 3:</strong></p>
<pre><code>输入:head = [1]
输出:[1]
</code></pre>
<p></p>
<p><strong>提示:</strong></p>
<ul>
<li>链表中节点的数目在范围 <code>[0, 100]</code> 内</li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>100</mn></mrow><annotation encoding="application/x-tex">\le 100</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">100</span></span></span></span></li>
</ul>
<h2 id="思路-4"><a class="anchor" href="#思路-4">#</a> 思路</h2>
<p><strong>一定要先画图模拟</strong></p>
<p>下面以交换 <code>cur</code> 与 <code>latter1</code> 为例,示意交换两个链表节点的过程:</p>
<ol>
<li>初始时:</li>
</ol>
<figure class="highlight mermaid"><figcaption data-lang="mermaid"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">graph</span> LR</pre></td></tr><tr><td data-num="2"></td><td><pre> pre <span class="token arrow operator">--></span> cur</pre></td></tr><tr><td data-num="3"></td><td><pre> cur <span class="token arrow operator">--></span> latter1</pre></td></tr><tr><td data-num="4"></td><td><pre> latter1 <span class="token arrow operator">--></span> latter2</pre></td></tr></tbody></table></figure><ol>
<li>令 <code>pre</code> 的 <code>next</code> 指针指向 <code>latter1</code></li>
</ol>
<figure class="highlight mermaid"><figcaption data-lang="mermaid"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">graph</span> LR</pre></td></tr><tr><td data-num="2"></td><td><pre> pre <span class="token arrow operator">-.-</span> cur</pre></td></tr><tr><td data-num="3"></td><td><pre> pre <span class="token arrow operator">--></span> latter1</pre></td></tr><tr><td data-num="4"></td><td><pre> cur <span class="token arrow operator">--></span> latter1</pre></td></tr><tr><td data-num="5"></td><td><pre> latter1 <span class="token arrow operator">--></span> latter2</pre></td></tr></tbody></table></figure><ol>
<li>保存指向 <code>latter2</code> 的指针 <code>temp</code> ,并且,令 <code>latter1</code> 的 <code>next</code> 指针指向 <code>cur</code></li>
</ol>
<figure class="highlight mermaid"><figcaption data-lang="mermaid"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">graph</span> LR<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="2"></td><td><pre> pre <span class="token arrow operator">--></span> latter1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> cur <span class="token arrow operator">--></span> latter1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> latter1 <span class="token arrow operator">--></span> cur<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="5"></td><td><pre> latter1 <span class="token arrow operator">-.-</span> latter2<span class="token punctuation">;</span></pre></td></tr></tbody></table></figure><ol start="4">
<li>令 <code>cur</code> 的 <code>next</code> 指针指向 <code>latter2</code></li>
</ol>
<figure class="highlight mermaid"><figcaption data-lang="mermaid"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">graph</span> LR<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="2"></td><td><pre> pre <span class="token arrow operator">--></span> latter1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> latter1 <span class="token arrow operator">--></span> cur<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> cur <span class="token arrow operator">-.-</span> latter1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="5"></td><td><pre> cur <span class="token arrow operator">--></span> latter2<span class="token punctuation">;</span></pre></td></tr></tbody></table></figure><ol start="5">
<li>通过以上步骤,实现节点 <code>cur</code> 与节点 <code>latter1</code> 的交换,所得链表为:</li>
</ol>
<figure class="highlight mermaid"><figcaption data-lang="mermaid"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">graph</span> LR<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="2"></td><td><pre> pre <span class="token arrow operator">--></span> latter1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> latter1 <span class="token arrow operator">--></span> cur<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> cur <span class="token arrow operator">--></span> latter2<span class="token punctuation">;</span></pre></td></tr></tbody></table></figure><h2 id="method-双指针"><a class="anchor" href="#method-双指针">#</a> Method: 双指针</h2>
<p>维护 <code>pre</code> 指针和 <code>cur</code> 指针,依照上述步骤完成 <code>cur</code> 和 <code>cur</code> 下个节点 <code>cur->next</code> 的交换</p>
<p>遍历 <code>cur</code> 指针,直到 <code>cur</code> 为空 或 <code>cur->next</code> 为空</p>
<ul>
<li>若 <code>cur</code> 为空,则链表节点数为偶数,此前的两两交换刚好完成所有节点交换</li>
<li>若 <code>cur</code> 不为空但 <code>cur->next</code> 为空,则链表节点数为奇数,两两交换后还剩最后一个节点,此时无需再进行交换</li>
</ul>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token comment">// 省略了结构体 ListNode 的定义</span></pre></td></tr><tr><td data-num="2"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">swapPairs</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 设置虚拟头节点,以便交换 head 节点及其下个节点</span></pre></td></tr><tr><td data-num="4"></td><td><pre> dummyHead<span class="token operator">-></span>next <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="5"></td><td><pre> ListNode<span class="token operator">*</span> cur <span class="token operator">=</span> head<span class="token punctuation">;</span> <span class="token comment">// 当前遍历节点</span></pre></td></tr><tr><td data-num="6"></td><td><pre> ListNode<span class="token operator">*</span> pre <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span> <span class="token comment">// 当前遍历节点 cur 的上个节点</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>cur <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> cur<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 交换 cur 及其下个节点</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token comment">// 拷贝指向 cur 下下个节点的指针(因为后续会修改 cur->next->next)</span></pre></td></tr><tr><td data-num="9"></td><td><pre> ListNode<span class="token operator">*</span> temp <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token comment">// 令 pre 的 next 指针指向 cur 的下个节点</span></pre></td></tr><tr><td data-num="11"></td><td><pre> pre<span class="token operator">-></span>next <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> <span class="token comment">// 令 cur 下个节点的 next 指针指向 cur</span></pre></td></tr><tr><td data-num="13"></td><td><pre> cur<span class="token operator">-></span>next<span class="token operator">-></span>next <span class="token operator">=</span> cur<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="14"></td><td><pre> <span class="token comment">// 令 cur 的 next 指针指向 temp</span></pre></td></tr><tr><td data-num="15"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> temp<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token comment">//pre 与 cur 同时向后移动</span></pre></td></tr><tr><td data-num="17"></td><td><pre> pre <span class="token operator">=</span> cur<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="18"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="19"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="20"></td><td><pre> <span class="token keyword">return</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">// 返回 dummyHead->next</span></pre></td></tr><tr><td data-num="21"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<h1 id="leetcode-19-删除链表的倒数第-n-个结点"><a class="anchor" href="#leetcode-19-删除链表的倒数第-n-个结点">#</a> LeetCode 19. 删除链表的倒数第 N 个结点</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/">LeetCode</a></p>
<p>给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。</p>
<p></p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode19_1.webp" alt=""></p>
<pre><code>输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
</code></pre>
<p><strong>示例 2:</strong></p>
<pre><code>输入:head = [1], n = 1
输出:[]
</code></pre>
<p><strong>示例 3:</strong></p>
<pre><code>输入:head = [1,2], n = 1
输出:[1]
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li>链表中结点的数目为 <code>sz</code></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">1 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>sz</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>30</mn></mrow><annotation encoding="application/x-tex">\le 30</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">30</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>100</mn></mrow><annotation encoding="application/x-tex">\le 100</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">100</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">1 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>n</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo></mrow><annotation encoding="application/x-tex">\le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span></span></span></span> <code>sz</code></li>
</ul>
<p><strong>进阶</strong>:你能尝试使用一趟扫描实现吗?</p>
<h2 id="method-双指针-2"><a class="anchor" href="#method-双指针-2">#</a> Method: 双指针</h2>
<p>解题思路如下:</p>
<ol>
<li>
<p>添加一个<strong>哑节点</strong>(dummy node),即,虚拟头节点,它的 <code>next</code> 指针指向链表的头节点</p>
</li>
<li>
<p>定义快慢指针 <code>fast</code> 和 <code>slow</code> ,初始值为哑结点,然后让 <code>fast</code> 指针移动 <code>n</code> 步,使得 <code>fast</code> 比 <code>slow</code> 超前 <code>n</code> 个节点</p>
</li>
<li>
<p>同时移动 <code>fast</code> 和 <code>slow</code> 指针,当 <code>fast</code> 遍历到链表的最后一个节点时( <code>fast != nullptr && fast->next == nullptr</code> ), <code>slow</code> 的下一个节点就是需要删除的节点</p>
</li>
<li>
<p>修改指针,即, <code>slow->next = slow->next->next</code> ,完成删除操作</p>
</li>
</ol>
<blockquote>
<p>因为添加了哑结点,如果需要删除的是头节点,同样可以采用上述步骤进行</p>
</blockquote>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">removeNthFromEnd</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">,</span> <span class="token keyword">int</span> n<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> head<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 创建哑结点</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode <span class="token operator">*</span>fast <span class="token operator">=</span> dummyHead<span class="token punctuation">,</span> <span class="token operator">*</span>slow <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span> <span class="token comment">// 初始化 fast 指针和 slow 指针</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span></pre></td></tr><tr><td data-num="5"></td><td><pre> fast <span class="token operator">=</span> fast<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">//fast 指针前进 n 步,即,比 slow 超前 n 步</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>fast <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> fast<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 两指针同时移动,直到 fast 走到最后一个节点</span></pre></td></tr><tr><td data-num="7"></td><td><pre> fast <span class="token operator">=</span> fast<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre> slow <span class="token operator">=</span> slow<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="9"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="10"></td><td><pre> ListNode<span class="token operator">*</span> node <span class="token operator">=</span> slow<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">// 暂存待删除节点</span></pre></td></tr><tr><td data-num="11"></td><td><pre> slow<span class="token operator">-></span>next <span class="token operator">=</span> slow<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">// 在链表中删除节点</span></pre></td></tr><tr><td data-num="12"></td><td><pre> <span class="token keyword">delete</span> node<span class="token punctuation">;</span> <span class="token comment">// 清除已删除节点的内存</span></pre></td></tr><tr><td data-num="13"></td><td><pre></pre></td></tr><tr><td data-num="14"></td><td><pre> ListNode<span class="token operator">*</span> ans <span class="token operator">=</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> <span class="token keyword">delete</span> dummyHead<span class="token punctuation">;</span> <span class="token comment">// 清除哑结点</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token keyword">return</span> ans<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="17"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>L</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(L)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">L</span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>L</mi></mrow><annotation encoding="application/x-tex">L</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal">L</span></span></span></span> 是链表的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<h1 id="leetcode-160-相交链表"><a class="anchor" href="#leetcode-160-相交链表">#</a> LeetCode 160. 相交链表</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/intersection-of-two-linked-lists/">LeetCode 160. Intersection of Two Linked Lists</a></p>
<p>给你两个单链表的头节点 <code>headA</code> 和 <code>headB</code> ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 <code>null</code> 。</p>
<p>图示两个链表在节点 <code>c1</code> 开始相交:</p>
<p><img loading="lazy" data-src="https://assets.leetcode.com/uploads/2021/03/05/160_statement.png" alt="" height="200px"></p>
<p>题目数据 <strong>保证</strong> 整个链式结构中不存在环。</p>
<p>注意,函数返回结果后,链表必须 <strong>保持其原始结构</strong> 。</p>
<p>评测系统 的输入如下(你设计的程序 不适用 此输入):</p>
<ul>
<li><code>intersectVal</code> - 相交的起始节点的值。如果不存在相交节点,这一值为 0</li>
<li><code>listA</code> - 第一个链表</li>
<li><code>listB</code> - 第二个链表</li>
<li><code>skipA</code> - 在 <code>listA</code> 中(从头节点开始)跳到交叉节点的节点数</li>
<li><code>skipB</code> - 在 <code>listB</code> 中(从头节点开始)跳到交叉节点的节点数</li>
</ul>
<p>评测系统将根据这些输入创建链式数据结构,并将两个头节点 <code>headA</code> 和 <code>headB</code> 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="https://assets.leetcode.com/uploads/2021/03/05/160_example_1_1.png" alt="" height="200px"></p>
<pre><code>输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,6,1,8,4,5]。在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
</code></pre>
<p><strong>示例 2:</strong></p>
<p><img loading="lazy" data-src="https://assets.leetcode.com/uploads/2021/03/05/160_example_2.png" alt="" height="200px"></p>
<pre><code>输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'
解释:相交节点的值为 2 (注意,如果两个链表相交则不能为 0)。从各自的表头开始算起,链表 A 为 [1,9,1,2,4],链表 B 为 [3,2,4]。在 A 中,相交节点前有 3 个节点;在 B 中,相交节点前有 1 个节点。
</code></pre>
<p><strong>示例 3:</strong></p>
<p><img loading="lazy" data-src="https://assets.leetcode.com/uploads/2021/03/05/160_example_3.png" alt=""></p>
<pre><code>输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。这两个链表不相交,因此返回 null 。
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li><code>listA</code> 中节点数目为 <code>m</code></li>
<li><code>listB</code> 中节点数目为 <code>n</code></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">1 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>m</code> , <code>n</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>3</mn><mo>×</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup></mrow><annotation encoding="application/x-tex">\le 3 \times 10^4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">3</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">1 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup></mrow><annotation encoding="application/x-tex">\le 10^5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>skipA</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo><</mo><mtext> </mtext><mi>m</mi></mrow><annotation encoding="application/x-tex">< m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord"> </span><span class="mord mathnormal">m</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>skipB</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo><</mo><mtext> </mtext><mi>n</mi></mrow><annotation encoding="application/x-tex">< n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mrel"><</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord"> </span><span class="mord mathnormal">n</span></span></span></span></li>
<li>如果 <code>listA</code> 和 <code>listB</code> 没有交点, <code>intersectVal</code> 为 <code>0</code></li>
<li>如果 <code>listA</code> 和 <code>listB</code> 有交点, <code>intersectVal == listA[skipA] == listB[skipB]</code></li>
</ul>
<p><strong>进阶</strong>:你能否设计一个时间复杂度 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>m</mi><mo>+</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(m + n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span> 、仅用 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span> 内存的解决方案?</p>
<h2 id="思路-5"><a class="anchor" href="#思路-5">#</a> 思路</h2>
<p>两链表的交点是指两链表对应 <strong>节点的指针相等</strong> (而不是数值相等),因此,需要找出两个链表相交节点的指针</p>
<p><strong>若两链表相交,则两链表的交点及以后节点均对应相等</strong></p>
<p>可将两链表 “尾端对齐” ,从较短链表的头节点开始检查,比较两链表对应节点是否相等</p>
<h2 id="method-双指针-3"><a class="anchor" href="#method-双指针-3">#</a> Method: 双指针</h2>
<p>算法流程:</p>
<ol>
<li>
<p>求出两个链表的长度 <code>m</code> 和 <code>n</code></p>
</li>
<li>
<p>定义指针 <code>curA</code> 指向长链表的头节点,指针 <code>curB</code> 指向短链表的头节点</p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode160_1.webp" alt=""></p>
</li>
<li>
<p>将指针 <code>curA</code> 移动到第 <code>m - n + 1</code> 个节点,使得两个指针后续可移动步数相同(类似于两链表尾端对齐)</p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode160_2.webp" alt=""></p>
</li>
<li>
<p>比较 <code>curA</code> 是否与 <code>curB</code> 相同</p>
<ul>
<li>若相同,则找到交点</li>
<li>若不相同,则同时将 <code>curA</code> 和 <code>curB</code> 向后移动,直到 <code>curA</code> 和 <code>curB</code> 到达链表末尾</li>
</ul>
</li>
<li>
<p>若未找到交点,返回空指针</p>
</li>
</ol>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">int</span> <span class="token function">getSize</span><span class="token punctuation">(</span>ListNode <span class="token operator">*</span>head<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 计算链表的长度</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token keyword">int</span> num <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode <span class="token operator">*</span>cur <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>cur <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="5"></td><td><pre> num<span class="token operator">++</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token keyword">return</span> num<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="9"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="10"></td><td><pre></pre></td></tr><tr><td data-num="11"></td><td><pre>ListNode <span class="token operator">*</span><span class="token function">getIntersectionNode</span><span class="token punctuation">(</span>ListNode <span class="token operator">*</span>headA<span class="token punctuation">,</span> ListNode <span class="token operator">*</span>headB<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="12"></td><td><pre> <span class="token keyword">int</span> m <span class="token operator">=</span> <span class="token function">getSize</span><span class="token punctuation">(</span>headA<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> <span class="token keyword">int</span> n <span class="token operator">=</span> <span class="token function">getSize</span><span class="token punctuation">(</span>headB<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="14"></td><td><pre> ListNode <span class="token operator">*</span>curA <span class="token operator">=</span> headA<span class="token punctuation">,</span> <span class="token operator">*</span>curB <span class="token operator">=</span> headB<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>m <span class="token operator"><</span> n<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//curA 指向长链,curB 指向短链</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token function">swap</span><span class="token punctuation">(</span>m<span class="token punctuation">,</span> n<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token function">swap</span><span class="token punctuation">(</span>curA<span class="token punctuation">,</span> curB<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="18"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="19"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator"><</span> m <span class="token operator">-</span> n<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token comment">// 令 curA 和 curB 的起点一致</span></pre></td></tr><tr><td data-num="20"></td><td><pre> curA <span class="token operator">=</span> curA<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="21"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>curA <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 遍历 curA 和 curB ,看两者是否相等</span></pre></td></tr><tr><td data-num="22"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>curA <span class="token operator">==</span> curB<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="23"></td><td><pre> <span class="token keyword">return</span> curA<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="24"></td><td><pre> curA <span class="token operator">=</span> curA<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="25"></td><td><pre> curB <span class="token operator">=</span> curB<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="26"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="27"></td><td><pre> <span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span> <span class="token comment">//curA 已经移动到尾后,此时仍未找到交点</span></pre></td></tr><tr><td data-num="28"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>m</mi><mo>+</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(m + n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 为两链表长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<p>参考:<a target="_blank" rel="noopener" href="https://www.programmercarl.com/%E9%9D%A2%E8%AF%95%E9%A2%9802.07.%E9%93%BE%E8%A1%A8%E7%9B%B8%E4%BA%A4.html#%E6%80%9D%E8%B7%AF">代码随想录:相交链表</a></p>
<h1 id="leetcode-141-环形链表"><a class="anchor" href="#leetcode-141-环形链表">#</a> LeetCode 141. 环形链表</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode.cn/problems/linked-list-cycle/">141. Linked List Cycle</a></p>
<p>给你一个链表的头节点 <code>head</code> ,判断链表中是否有环。</p>
<p>如果链表中有某个节点,可以通过连续跟踪 <code>next</code> 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 <code>pos</code> 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意: <code>pos</code> 不作为参数进行传递 。仅仅是为了标识链表的实际情况。</p>
<p>如果链表中存在环 ,则返回 <code>true</code> 。 否则,返回 <code>false</code> 。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode141_Example1.webp" alt=""></p>
<pre><code>输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点
</code></pre>
<p><strong>示例 2:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode141_Example2.webp" alt=""></p>
<pre><code>输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点
</code></pre>
<p><strong>示例 3:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode141_Example3.webp" alt=""></p>
<pre><code>输入:head = [1], pos = -1
输出:false
解释:链表中没有环
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li>链表中节点的数目范围是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[0, 10^4]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>−</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup><mo>≤</mo></mrow><annotation encoding="application/x-tex">-10^5 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9501em;vertical-align:-0.136em;"></span><span class="mord">−</span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup></mrow><annotation encoding="application/x-tex">\le 10^5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span></span></span></span></li>
<li><code>pos</code> 为 -1 或者链表中的一个 有效索引</li>
</ul>
<p><strong>进阶</strong>:你能用 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span>(即,常量)内存解决此问题吗?</p>
<h2 id="method-双指针-4"><a class="anchor" href="#method-双指针-4">#</a> Method: 双指针</h2>
<p>算法思路:</p>
<p>定义 fast 和 slow 指针,均从头结点出发</p>
<ul>
<li>fast 指针每次移动两个节点</li>
<li>slow 指针每次移动一个节点</li>
</ul>
<p>如果 fast 和 slow 指针在途中相遇,说明链表有环</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">bool</span> <span class="token function">hasCycle</span><span class="token punctuation">(</span>ListNode <span class="token operator">*</span>head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode<span class="token operator">*</span> fast <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> slow <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>fast <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> fast<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="5"></td><td><pre> fast <span class="token operator">=</span> fast<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre> slow <span class="token operator">=</span> slow<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>fast <span class="token operator">==</span> slow<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="9"></td><td><pre> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<h1 id="leetcode-142-环形链表-ii"><a class="anchor" href="#leetcode-142-环形链表-ii">#</a> LeetCode 142. 环形链表 II</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode-cn.com/problems/linked-list-cycle-ii/">LeetCode 142. Linked List Cycle II</a></p>
<p>给定一个链表的头节点 <code>head</code> ,返回链表开始入环的第一个节点。 如果链表无环,则返回 <code>null</code> 。</p>
<p>如果链表中有某个节点,可以通过连续跟踪 <code>next</code> 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 <code>pos</code> 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 <code>pos</code> 是 -1,则在该链表中没有环。注意: <code>pos</code> 不作为参数进行传递,仅仅是为了标识链表的实际情况。</p>
<p><strong>不允许修改</strong> 链表。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode142_1.webp" alt="示例 1"></p>
<pre><code>输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点
</code></pre>
<p><strong>示例 2:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode142_2.webp" alt="示例 2"></p>
<pre><code>输入:head = [1,2], pos = 0
输出:返回索引为 0 的链表节点
解释:链表中有一个环,其尾部连接到第一个节点
</code></pre>
<p><strong>示例 3:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode142_3.webp" alt="示例 3"></p>
<pre><code>输入:head = [1], pos = -1
输出:返回 null
解释:链表中没有环
</code></pre>
<p></p>
<p><strong>提示:</strong></p>
<ul>
<li>链表中节点的数目范围在范围 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>0</mn><mo separator="true">,</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[0, 10^4]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span> 内</li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>−</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup><mo>≤</mo></mrow><annotation encoding="application/x-tex">- 10^5 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9501em;vertical-align:-0.136em;"></span><span class="mord">−</span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup></mrow><annotation encoding="application/x-tex">\le 10^5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span></span></span></span></li>
<li><code>pos</code> 为 -1 或者链表中的一个 有效索引</li>
</ul>
<p><strong>进阶</strong>:你是否可以使用 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span> 空间解决此题?</p>
<h2 id="思路-6"><a class="anchor" href="#思路-6">#</a> 思路</h2>
<p>关键点一:判断是否有环</p>
<p>定义 <code>fast</code> 和 <code>slow</code> 指针,从头结点出发, <code>fast</code> 指针每次移动两个节点, <code>slow</code> 指针每次移动一个节点,如果 <code>fast</code> 和 <code>slow</code> 指针在途中相遇 ,说明这个链表有环</p>
<ul>
<li>
<p>若 <code>fast</code> 与 <code>slow</code> 相遇,则一定有环:因为 <code>fast</code> 超前 <code>slow</code> ,相遇时二者一定都在环内</p>
</li>
<li>
<p>若链表有环,则 <code>fast</code> 与 <code>slow</code> 一定相遇:当 <code>slow</code> 步入到环内时,由于 <code>fast</code> 指针每次移动相对于 <code>slow</code> 指针而言都是移动一位,故而一定会相遇</p>
</li>
</ul>
<p>关键点二:确定环的入口</p>
<blockquote>
<p><code>slow</code> 指针在第一次遍历链表环时,就一定会与 <code>fast</code> 指针相遇。具体证明过程见 <a target="_blank" rel="noopener" href="https://www.programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#%E6%80%9D%E8%B7%AF">环形链表:补充</a></p>
</blockquote>
<p>假设从 头结点 到 环形入口节点 的节点数为 <code>x</code> ,从 环形入口节点 到 <code>fast</code> 指针与 <code>slow</code> 指针相遇节点 的节点数为 y ,从 相遇节点 再到 环形入口节点 的节点数为 <code>z</code></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode142_4.webp" alt=""></p>
<p>相遇时 <code>slow</code> 指针走过的节点数为 <code>x + y</code> , <code>fast</code> 指针走过的节点数为 <code>x + y + n (y + z)</code> ,其中 <code>n</code> 为 <code>fast</code> 指针在环内走过的圈数</p>
<p>由于 <code>fast</code> 指针一步两节点, <code>slow</code> 指针一步一节点,则 <code>fast</code> 走过节点数为 <code>slow</code> 指针走过节点数的 <code>2</code> 倍,即: <code>2 (x + y) = x + y + n (y + z)</code></p>
<p>故而,环形的入口节点 <code>x</code> 应满足 <strong> <code>x = (n - 1) (y + z) + z</code> </strong> ,注意 <code>n</code> 一定大于等于 <code>1</code> (否则, <code>fast</code> 不可能与 <code>slow</code> 相遇)</p>
<p>这意味着,<strong>指针 <code>index1</code> 从头结点出发,与此同时,指针 <code>index2</code> 从相遇节点出发,两指针每次均只走一个节点,这两个指针相遇的节点就是环形入口的节点</strong></p>
<p><img loading="lazy" data-src="https://code-thinking.cdn.bcebos.com/gifs/141.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8.gif" alt=""></p>
<p>参考:<a target="_blank" rel="noopener" href="https://www.programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#%E6%80%9D%E8%B7%AF">代码随想录:环形链表 II</a></p>
<h2 id="method-快慢指针"><a class="anchor" href="#method-快慢指针">#</a> Method: 快慢指针</h2>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode <span class="token operator">*</span><span class="token function">detectCycle</span><span class="token punctuation">(</span>ListNode <span class="token operator">*</span>head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode <span class="token operator">*</span>fast <span class="token operator">=</span> head<span class="token punctuation">,</span> <span class="token operator">*</span>slow <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>fast <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> fast<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//fast 到达链表最后一个节点时,循环结束</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token comment">//fast 指针每步走两节点,slow 指针每步走一节点</span></pre></td></tr><tr><td data-num="5"></td><td><pre> fast <span class="token operator">=</span> fast<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre> slow <span class="token operator">=</span> slow<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>fast <span class="token operator">==</span> slow<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//fast 与 slow 相遇</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token comment">//index1 指针从 head 出发,index2 指针从 fast 与 slow 相遇点出发,找出 index1 与 index2 的相遇位置</span></pre></td></tr><tr><td data-num="9"></td><td><pre> ListNode <span class="token operator">*</span>index1 <span class="token operator">=</span> head<span class="token punctuation">,</span> <span class="token operator">*</span>index2 <span class="token operator">=</span> fast<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>index1 <span class="token operator">!=</span> index2<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="11"></td><td><pre> index1 <span class="token operator">=</span> index1<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> index2 <span class="token operator">=</span> index2<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="14"></td><td><pre> <span class="token keyword">return</span> index1<span class="token punctuation">;</span> <span class="token comment">//index1 与 index2 的相遇点即为环形入口</span></pre></td></tr><tr><td data-num="15"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token comment">//fast 不与 slow 相遇,不存在环形</span></pre></td></tr><tr><td data-num="18"></td><td><pre> <span class="token keyword">return</span> <span class="token constant">NULL</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="19"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span> ,指针 <code>slow</code> 与指针 <code>index1</code> 走过的长度均不超过链表节点数目 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span></p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span> ,仅使用指针</p>
<h1 id="leetcode-21-合并两个有序链表"><a class="anchor" href="#leetcode-21-合并两个有序链表">#</a> LeetCode 21. 合并两个有序链表</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode.cn/problems/merge-two-sorted-lists/">21. Merge Two Sorted Lists</a></p>
<p>将两个升序链表合并为一个新的 <strong>升序</strong> 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode21_Example1.webp" alt="" height="200px"></p>
<pre><code>输入:list1 = [1,2,4], list2 = [1,3,4]
输出:[1,1,2,3,4,4]
</code></pre>
<p><strong>示例 2:</strong></p>
<pre><code>输入:list1 = [], list2 = []
输出:[]
</code></pre>
<p><strong>示例 3:</strong></p>
<pre><code>输入:list1 = [], list2 = [0]
输出:[0]
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li>两个链表的节点数目范围是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>0</mn><mo separator="true">,</mo><mn>50</mn><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[0, 50]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">50</span><span class="mclose">]</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>−</mo><mn>100</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">-100 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">−</span><span class="mord">100</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> Node.val <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>100</mn></mrow><annotation encoding="application/x-tex">\le 100</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">100</span></span></span></span></li>
<li><code>list1</code> 和 <code>list2</code> 均按 <strong>非递减顺序</strong> 排列</li>
</ul>
<h2 id="method-1-递归"><a class="anchor" href="#method-1-递归">#</a> Method 1: 递归</h2>
<p>单层递归的逻辑:</p>
<ul>
<li>
<p>若 <code>list1 == nullptr</code> ,则可取 <code>list2</code> 作为目标链表</p>
</li>
<li>
<p>若 <code>list2 == nullptr</code> ,则可取 <code>list1</code> 作为目标链表</p>
</li>
<li>
<p>若 <code>list1->val <= list2->val</code> ,则应将 <code>list1</code> 添加到目标链表,并递归调用 <code>mergeTwoLists(list1->next, list2)</code> 以确定目标链表中的下一个节点,即, <code>list1->next = mergeTwoLists(list1->next, list2)</code></p>
</li>
<li>
<p>若 <code>list1->val > list2->val</code> ,则应将 <code>list2</code> 添加到目标链表,并递归调用 <code>mergeTwoLists(list1, list2->next)</code> 以确定目标链表中的下一个节点,即, <code>list2->next = mergeTwoLists(list1, list2->next)</code></p>
</li>
</ul>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">mergeTwoLists</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> list1<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> list2<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>list1 <span class="token operator">==</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token keyword">return</span> list2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>list2 <span class="token operator">==</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token keyword">return</span> list1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>list1<span class="token operator">-></span>val <span class="token operator"><=</span> list2<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="5"></td><td><pre> list1<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token function">mergeTwoLists</span><span class="token punctuation">(</span>list1<span class="token operator">-></span>next<span class="token punctuation">,</span> list2<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token keyword">return</span> list1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="8"></td><td><pre> list2<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token function">mergeTwoLists</span><span class="token punctuation">(</span>list1<span class="token punctuation">,</span> list2<span class="token operator">-></span>next<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="9"></td><td><pre> <span class="token keyword">return</span> list2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="11"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>m</mi><mo>+</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(m + n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 分别是链表 <code>list1</code> 和链表 <code>list2</code> 的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>m</mi><mo>+</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(m + n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,递归所需栈空间</p>
<h2 id="method-2-迭代"><a class="anchor" href="#method-2-迭代">#</a> Method 2: 迭代</h2>
<p>算法思路:</p>
<p>定义一个虚拟头节点(哑节点) <code>dummyHead</code> ,初始化为 <code>ListNode(0)</code> ,其 <code>next</code> 指针指向目标链表的头节点</p>
<p>定义一个指针 <code>prev</code> 指向目标链接的末尾,初始化 <code>prev</code> 为 <code>dummyHead</code> ,其 <code>next</code> 指针将指向新添加的节点</p>
<p>遍历链表 <code>list1</code> 和 <code>list2</code> ,直到其中一个链表为空:</p>
<ul>
<li>若 <code>list1->val <= list2->val</code> ,则应将 <code>list1</code> 添加到目标链表,即 <code>prev->next = list1</code> ,并将 <code>list1</code> 和 <code>prev</code> 分别向后移动一步</li>
<li>若 <code>list1->val > list2->val</code> ,则应将 <code>list2</code> 添加到目标链表,即 <code>prev->next = list2</code> ,并将 <code>list2</code> 和 <code>prev</code> 分别向后移动一步</li>
</ul>
<p>循环结束后, <code>list1</code> 和 <code>list2</code> 最多只有一个非空,直接将目标链表的末尾指向非空链表即可</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">mergeTwoLists</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> list1<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> list2<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> prev <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>list1 <span class="token operator">&&</span> list2<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>list1<span class="token operator">-></span>val <span class="token operator"><=</span> list2<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="6"></td><td><pre> prev<span class="token operator">-></span>next <span class="token operator">=</span> list1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> list1 <span class="token operator">=</span> list1<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="9"></td><td><pre> prev<span class="token operator">-></span>next <span class="token operator">=</span> list2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> list2 <span class="token operator">=</span> list2<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="11"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="12"></td><td><pre> prev <span class="token operator">=</span> prev<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="14"></td><td><pre> prev<span class="token operator">-></span>next <span class="token operator">=</span> list1 <span class="token operator">==</span> <span class="token keyword">nullptr</span> <span class="token operator">?</span> list2 <span class="token operator">:</span> list1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> ListNode<span class="token operator">*</span> ans <span class="token operator">=</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token keyword">delete</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token keyword">return</span> ans<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="18"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>m</mi><mo>+</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(m + n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">m</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>m</mi></mrow><annotation encoding="application/x-tex">m</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">m</span></span></span></span> 和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 分别是链表 <code>list1</code> 和链表 <code>list2</code> 的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<p>参考:<a target="_blank" rel="noopener" href="https://leetcode.cn/problems/merge-two-sorted-lists/solution/he-bing-liang-ge-you-xu-lian-biao-by-leetcode-solu/">力扣官方题解</a></p>
<h1 id="leetcode-23-合并-k-个升序链表"><a class="anchor" href="#leetcode-23-合并-k-个升序链表">#</a> LeetCode 23. 合并 K 个升序链表</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode.cn/problems/merge-k-sorted-lists/">23. Merge k Sorted Lists</a></p>
<p>给你一个链表数组,每个链表都已经按升序排列。</p>
<p>请你将所有链表合并到一个升序链表中,返回合并后的链表。</p>
<p><strong>示例 1:</strong></p>
<pre><code>输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6
</code></pre>
<p><strong>示例 2:</strong></p>
<pre><code>输入:lists = []
输出:[]
</code></pre>
<p><strong>示例 3:</strong></p>
<pre><code>输入:lists = [[]]
输出:[]
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li><code>k == lists.length</code></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>k</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup></mrow><annotation encoding="application/x-tex">\le 10^4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>lists[i].length</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>500</mn></mrow><annotation encoding="application/x-tex">\le 500</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">500</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup><mo>≤</mo></mrow><annotation encoding="application/x-tex">10^4 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9501em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>lists[i][j]</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup></mrow><annotation encoding="application/x-tex">\le 10^4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span></span></span></span></li>
<li><code>lists[i]</code> 按 升序 排列</li>
<li><code>lists[i].length</code> 的总和不超过 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup></mrow><annotation encoding="application/x-tex">10^4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<h2 id="method-1-顺序合并"><a class="anchor" href="#method-1-顺序合并">#</a> Method 1: 顺序合并</h2>
<p>算法思路:首先将 <code>lists[0]</code> 和 <code>lists[1]</code> 合并,得到链表 <code>ans</code> ,再依次将 <code>ans</code> 与 <code>lists[2]</code> , ... , <code>lists[lists.size() - 1]</code> 合并</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">merge2Lists</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> l1<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> l2<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 合并链表 l1 和 l2</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> tail <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>l1 <span class="token operator">&&</span> l2<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>l1<span class="token operator">-></span>val <span class="token operator"><=</span> l2<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="6"></td><td><pre> tail<span class="token operator">-></span>next <span class="token operator">=</span> l1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> l1 <span class="token operator">=</span> l1<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="9"></td><td><pre> tail<span class="token operator">-></span>next <span class="token operator">=</span> l2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> l2 <span class="token operator">=</span> l2<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="11"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="12"></td><td><pre> tail <span class="token operator">=</span> tail<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="14"></td><td><pre> tail<span class="token operator">-></span>next <span class="token operator">=</span> l1 <span class="token operator">?</span> l1 <span class="token operator">:</span> l2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> ListNode<span class="token operator">*</span> head <span class="token operator">=</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token keyword">delete</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token keyword">return</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="18"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="19"></td><td><pre></pre></td></tr><tr><td data-num="20"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">mergeKLists</span><span class="token punctuation">(</span>vector<span class="token operator"><</span>ListNode<span class="token operator">*</span><span class="token operator">></span><span class="token operator">&</span> lists<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="21"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>lists<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="22"></td><td><pre> ListNode<span class="token operator">*</span> ans <span class="token operator">=</span> lists<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="23"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><</span> lists<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 顺序合并</span></pre></td></tr><tr><td data-num="24"></td><td><pre> ans <span class="token operator">=</span> <span class="token function">merge2Lists</span><span class="token punctuation">(</span>ans<span class="token punctuation">,</span> lists<span class="token punctuation">[</span>i<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="25"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="26"></td><td><pre> <span class="token keyword">return</span> ans<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="27"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><msup><mi>k</mi><mn>2</mn></msup><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(k^2 n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span> ,其中,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> 是 lists 中的链表条数,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 是 lists 中链表的最大长度</p>
<ul>
<li>将链表 <code>ans</code> 与链表 <code>lists[i]</code> 合并的时间复杂度为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo>+</mo><mo stretchy="false">(</mo><mi>i</mi><mo>−</mo><mn>1</mn><mo stretchy="false">)</mo><mo>×</mo><mi>n</mi><mo stretchy="false">)</mo><mo>=</mo><mi>O</mi><mo stretchy="false">(</mo><mi>i</mi><mo>×</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n + (i - 1) \times n) = O(i \times n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">+</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">−</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></li>
<li>总的时间复杂度为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><msubsup><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo stretchy="false">(</mo><mi>i</mi><mo>×</mo><mi>n</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>=</mo><mi>O</mi><mo stretchy="false">(</mo><msup><mi>k</mi><mn>2</mn></msup><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\sum\limits_{i = 1}^{n} (i \times n)) = O(k^2 n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.3291em;vertical-align:-0.9777em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3514em;"><span style="top:-2.1223em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop op-symbol small-op">∑</span></span></span><span style="top:-3.95em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.9777em;"><span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathnormal">i</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal">n</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></li>
</ul>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<h2 id="method-2-分治"><a class="anchor" href="#method-2-分治">#</a> Method 2: 分治</h2>
<p>算法思路:可以用分治的思路来合并,即:</p>
<ul>
<li>首先将 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi></mrow><annotation encoding="application/x-tex">k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span> 条链表进行配对,将每一对链表进行合并,由此可得到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mi mathvariant="normal">/</mi><mn>2</mn></mrow><annotation encoding="application/x-tex">k / 2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord">/2</span></span></span></span> 条链表(链表的最大长度为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mi>n</mi><mi mathvariant="normal">/</mi><mi>k</mi></mrow><annotation encoding="application/x-tex">2 n / k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">2</span><span class="mord mathnormal">n</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>)</li>
<li>继续将 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mi mathvariant="normal">/</mi><mn>2</mn></mrow><annotation encoding="application/x-tex">k / 2</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord">/2</span></span></span></span> 条链表进行配对,合并每一对链表,可得到 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mi mathvariant="normal">/</mi><mn>4</mn></mrow><annotation encoding="application/x-tex">k / 4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord">/4</span></span></span></span> 条链表(链表的最大长度为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>4</mn><mi>n</mi><mi mathvariant="normal">/</mi><mi>k</mi></mrow><annotation encoding="application/x-tex">4 n / k</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord">4</span><span class="mord mathnormal">n</span><span class="mord">/</span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span></span></span>)</li>
<li>重复该过程,直到所有链表均已合并完成</li>
</ul>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">merge2Lists</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> l1<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> l2<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 合并链表 l1 和 l2</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> tail <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>l1 <span class="token operator">&&</span> l2<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>l1<span class="token operator">-></span>val <span class="token operator"><=</span> l2<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="6"></td><td><pre> tail<span class="token operator">-></span>next <span class="token operator">=</span> l1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> l1 <span class="token operator">=</span> l1<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="9"></td><td><pre> tail<span class="token operator">-></span>next <span class="token operator">=</span> l2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> l2 <span class="token operator">=</span> l2<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="11"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="12"></td><td><pre> tail <span class="token operator">=</span> tail<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="14"></td><td><pre> tail<span class="token operator">-></span>next <span class="token operator">=</span> l1 <span class="token operator">?</span> l1 <span class="token operator">:</span> l2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> ListNode<span class="token operator">*</span> head <span class="token operator">=</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token keyword">delete</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token keyword">return</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="18"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="19"></td><td><pre></pre></td></tr><tr><td data-num="20"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">merge</span><span class="token punctuation">(</span>vector<span class="token operator"><</span>ListNode<span class="token operator">*</span><span class="token operator">></span><span class="token operator">&</span> lists<span class="token punctuation">,</span> <span class="token keyword">int</span> left<span class="token punctuation">,</span> <span class="token keyword">int</span> right<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 合并 [left, right] 索引范围内的链表</span></pre></td></tr><tr><td data-num="21"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>left <span class="token operator">==</span> right<span class="token punctuation">)</span> <span class="token keyword">return</span> lists<span class="token punctuation">[</span>left<span class="token punctuation">]</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="22"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>left <span class="token operator">></span> right<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="23"></td><td><pre> <span class="token keyword">int</span> mid <span class="token operator">=</span> <span class="token punctuation">(</span>left <span class="token operator">+</span> right<span class="token punctuation">)</span> <span class="token operator">>></span> <span class="token number">1</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="24"></td><td><pre> ListNode<span class="token operator">*</span> l1 <span class="token operator">=</span> <span class="token function">merge</span><span class="token punctuation">(</span>lists<span class="token punctuation">,</span> left<span class="token punctuation">,</span> mid<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 合并 [left, mid] 索引范围内的链表</span></pre></td></tr><tr><td data-num="25"></td><td><pre> ListNode<span class="token operator">*</span> l2 <span class="token operator">=</span> <span class="token function">merge</span><span class="token punctuation">(</span>lists<span class="token punctuation">,</span> mid <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">,</span> right<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 合并 [mid + 1, right] 索引范围内的链表</span></pre></td></tr><tr><td data-num="26"></td><td><pre> <span class="token keyword">return</span> <span class="token function">merge2Lists</span><span class="token punctuation">(</span>l1<span class="token punctuation">,</span> l2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 合并成一条链表</span></pre></td></tr><tr><td data-num="27"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="28"></td><td><pre></pre></td></tr><tr><td data-num="29"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">mergeKLists</span><span class="token punctuation">(</span>vector<span class="token operator"><</span>ListNode<span class="token operator">*</span><span class="token operator">></span><span class="token operator">&</span> lists<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="30"></td><td><pre> <span class="token keyword">return</span> <span class="token function">merge</span><span class="token punctuation">(</span>lists<span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> lists<span class="token punctuation">.</span><span class="token function">size</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="31"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>k</mi><mi>n</mi><mo>×</mo><mi>log</mi><mo></mo><mi>k</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(k n \times \log{k})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">kn</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span><span class="mclose">)</span></span></span></span></p>
<ul>
<li>第 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>i</mi></mrow><annotation encoding="application/x-tex">i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6595em;"></span><span class="mord mathnormal">i</span></span></span></span> 轮合并 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>k</mi><mi mathvariant="normal">/</mi><msup><mn>2</mn><mi>i</mi></msup></mrow><annotation encoding="application/x-tex">k / 2^i</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0747em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.03148em;">k</span><span class="mord">/</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8247em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span></span></span></span> 对链表,其中,合并每一对的时间复杂度为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><msup><mn>2</mn><mi>i</mi></msup><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(2^i n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0747em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8247em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></li>
<li>总的时间复杂度为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><msubsup><mo>∑</mo><mrow><mi>i</mi><mo>=</mo><mn>1</mn></mrow><mi>n</mi></msubsup><mo stretchy="false">(</mo><mfrac><mi>k</mi><msup><mn>2</mn><mi>i</mi></msup></mfrac><mo>×</mo><msup><mn>2</mn><mi>i</mi></msup><mi>n</mi><mo stretchy="false">)</mo><mo stretchy="false">)</mo><mo>=</mo><mi>O</mi><mo stretchy="false">(</mo><mi>k</mi><mi>n</mi><mo>×</mo><mi>log</mi><mo></mo><mi>k</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\sum\limits_{i = 1}^{n} (\frac{k}{2^i} \times 2^i n)) = O(k n \times \log{k})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:2.3291em;vertical-align:-0.9777em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mop op-limits"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:1.3514em;"><span style="top:-2.1223em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">i</span><span class="mrel mtight">=</span><span class="mord mtight">1</span></span></span></span><span style="top:-3em;"><span class="pstrut" style="height:3em;"></span><span><span class="mop op-symbol small-op">∑</span></span></span><span style="top:-3.95em;margin-left:0em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight">n</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.9777em;"><span></span></span></span></span></span><span class="mopen">(</span><span class="mord"><span class="mopen nulldelimiter"></span><span class="mfrac"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.8801em;"><span style="top:-2.655em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mtight">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.7571em;"><span style="top:-2.786em;margin-right:0.0714em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span></span></span></span><span style="top:-3.23em;"><span class="pstrut" style="height:3em;"></span><span class="frac-line" style="border-bottom-width:0.04em;"></span></span><span style="top:-3.394em;"><span class="pstrut" style="height:3em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathnormal mtight" style="margin-right:0.03148em;">k</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.345em;"><span></span></span></span></span></span><span class="mclose nulldelimiter"></span></span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0747em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord">2</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8247em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathnormal mtight">i</span></span></span></span></span></span></span></span><span class="mord mathnormal">n</span><span class="mclose">))</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">kn</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span><span class="mclose">)</span></span></span></span></li>
</ul>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo></mo><mi>k</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\log{k})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal" style="margin-right:0.03148em;">k</span></span><span class="mclose">)</span></span></span></span>,递归( <code>merge</code> 函数)所需栈空间</p>
<p>参考:<a target="_blank" rel="noopener" href="https://leetcode.cn/problems/merge-k-sorted-lists/solution/he-bing-kge-pai-xu-lian-biao-by-leetcode-solutio-2/">力扣官方题解</a></p>
<h1 id="剑指-offer-06-从尾到头打印链表"><a class="anchor" href="#剑指-offer-06-从尾到头打印链表">#</a> 剑指 Offer 06. 从尾到头打印链表</h1>
<p>输入一个链表的头节点,从尾到头反过来返回每个节点的值(用数组返回)</p>
<p><strong>示例 1:</strong></p>
<pre><code>输入:head = [1,3,2]
输出:[2,3,1]
</code></pre>
<h2 id="method-1-遍历添加"><a class="anchor" href="#method-1-遍历添加">#</a> Method 1: 遍历添加</h2>
<p>链表长度未知</p>
<p>先统计链表节点的个数 <code>count</code> ,然后定义一个数组,逆序记录链表各节点的值</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> <span class="token function">reversePrint</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token comment">// 统计链表的节点数</span></pre></td></tr><tr><td data-num="3"></td><td><pre> <span class="token keyword">int</span> count <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> ListNode <span class="token operator">*</span>node <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>node <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="6"></td><td><pre> count<span class="token operator">++</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> node <span class="token operator">=</span> node<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="9"></td><td><pre> <span class="token comment">// 创建数组</span></pre></td></tr><tr><td data-num="10"></td><td><pre> vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> <span class="token function">nums</span><span class="token punctuation">(</span>count<span class="token punctuation">,</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="11"></td><td><pre> <span class="token comment">// 逆序记录链表节点的值</span></pre></td></tr><tr><td data-num="12"></td><td><pre> node <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> count <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span> node <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> i<span class="token operator">--</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="14"></td><td><pre> nums<span class="token punctuation">[</span>i<span class="token punctuation">]</span> <span class="token operator">=</span> node<span class="token operator">-></span>val<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> node <span class="token operator">=</span> node<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="17"></td><td><pre> <span class="token keyword">return</span> nums<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="18"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>N</mi></mrow><annotation encoding="application/x-tex">N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span></span></span></span> 为链表长度,遍历统计、遍历修改皆使用 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span> 时间</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,新建了一个 <code>vector</code> 容器</p>
<h2 id="method-2-递归-2"><a class="anchor" href="#method-2-递归-2">#</a> Method 2: 递归</h2>
<p>利用递归,先递推至链表末端;回溯时,依次将节点值加入数组,即可实现链表值的逆序输出</p>
<p>算法流程:</p>
<ol>
<li>
<p>终止条件:当 <code>head == nullptr</code> 时,代表越过了链表尾节点,则返回空列表</p>
</li>
<li>
<p>递推工作:访问下一节点 <code>head->next</code></p>
</li>
<li>
<p>回溯阶段:将当前节点值 <code>head->val</code> 加入数组 <code>res</code></p>
</li>
</ol>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">class</span> <span class="token class-name">Solution</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre><span class="token keyword">public</span><span class="token operator">:</span></pre></td></tr><tr><td data-num="3"></td><td><pre> vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> <span class="token function">reversePrint</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token function">recur</span><span class="token punctuation">(</span>head<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token keyword">return</span> res<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="7"></td><td><pre></pre></td></tr><tr><td data-num="8"></td><td><pre><span class="token keyword">private</span><span class="token operator">:</span></pre></td></tr><tr><td data-num="9"></td><td><pre> vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> res<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token keyword">void</span> <span class="token function">recur</span><span class="token punctuation">(</span>ListNode <span class="token operator">*</span>head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="11"></td><td><pre> <span class="token keyword">if</span><span class="token punctuation">(</span>head <span class="token operator">==</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token keyword">return</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> <span class="token function">recur</span><span class="token punctuation">(</span>head<span class="token operator">-></span>next<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> res<span class="token punctuation">.</span><span class="token function">push_back</span><span class="token punctuation">(</span>head<span class="token operator">-></span>val<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="14"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="15"></td><td><pre><span class="token punctuation">}</span><span class="token punctuation">;</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,遍历链表,递归 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>N</mi></mrow><annotation encoding="application/x-tex">N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span></span></span></span> 次</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,递归需要使用 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span> 的栈空间</p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/%E5%89%91%E6%8C%87Offer06_1.webp" alt=""><br>
注:图解是以 Python 代码为例</p>
<h2 id="method-3-栈"><a class="anchor" href="#method-3-栈">#</a> Method 3: 栈</h2>
<p>链表只能 从前至后 访问每个节点,而这里要求 <strong>逆序输出</strong> 各节点值,这种 <strong>先入后出</strong> 的需求可以借助 <strong>栈</strong> 来实现</p>
<p>算法流程:</p>
<ol>
<li>
<p>入栈:遍历链表,将各节点值 <code>push</code> 入栈</p>
</li>
<li>
<p>出栈:将各节点值 <code>pop</code> 出栈,存储于数组并返回</p>
</li>
</ol>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> <span class="token function">reversePrint</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> stack<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> stk<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> <span class="token keyword">while</span><span class="token punctuation">(</span>head <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="4"></td><td><pre> stk<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>head<span class="token operator">-></span>val<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 入栈,在栈顶增加元素</span></pre></td></tr><tr><td data-num="5"></td><td><pre> head <span class="token operator">=</span> head<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="7"></td><td><pre> vector<span class="token operator"><</span><span class="token keyword">int</span><span class="token operator">></span> res<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token keyword">while</span><span class="token punctuation">(</span><span class="token operator">!</span>stk<span class="token punctuation">.</span><span class="token function">empty</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 判断堆栈是否为空</span></pre></td></tr><tr><td data-num="9"></td><td><pre> res<span class="token punctuation">.</span><span class="token function">push_back</span><span class="token punctuation">(</span>stk<span class="token punctuation">.</span><span class="token function">top</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//top () 函数返回栈顶元素</span></pre></td></tr><tr><td data-num="10"></td><td><pre> stk<span class="token punctuation">.</span><span class="token function">pop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 出栈,移除栈顶元素</span></pre></td></tr><tr><td data-num="11"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="12"></td><td><pre> <span class="token keyword">return</span> res<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,一共有 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>N</mi></mrow><annotation encoding="application/x-tex">N</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6833em;"></span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span></span></span></span> 次的入栈和出栈<br>
空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span>,辅助栈 <code>stack</code> 和数组 <code>res</code> 各使用 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>N</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(N)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal" style="margin-right:0.10903em;">N</span><span class="mclose">)</span></span></span></span> 的额外空间</p>
<h1 id="leetcode-146-lru缓存"><a class="anchor" href="#leetcode-146-lru缓存">#</a> LeetCode 146. LRU 缓存</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode.cn/problems/lru-cache/">146. LRU Cache</a></p>
<p>请你设计并实现一个满足 <strong>LRU (最近最少使用) 缓存</strong> 约束的数据结构。</p>
<p>实现 <code>LRUCache</code> 类:</p>
<ul>
<li>
<p><code>LRUCache(int capacity)</code> 以 <strong>正整数</strong> 作为容量 <code>capacity</code> 初始化 LRU 缓存</p>
</li>
<li>
<p><code>int get(int key)</code> 如果关键字 <code>key</code> 存在于缓存中,则返回关键字的值,否则返回 <code>-1</code> 。</p>
</li>
<li>
<p><code>void put(int key, int value)</code> 如果关键字 <code>key</code> 已经存在,则变更其数据值 <code>value</code> ;如果不存在,则向缓存中插入该组 <code>key-value</code> 。如果插入操作导致关键字数量超过 <code>capacity</code> ,则应该 逐出 最久未使用的关键字。</p>
</li>
</ul>
<p>函数 <code>get</code> 和 <code>put</code> 必须以 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span> 的平均时间复杂度运行。</p>
<p><strong>示例 1:</strong></p>
<pre><code>输入:
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出:
[null, null, null, 1, null, -1, null, -1, 3, 4]
解释:
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1); // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2); // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1); // 返回 -1 (未找到)
lRUCache.get(3); // 返回 3
lRUCache.get(4); // 返回 4
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>1</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">1 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">1</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>capacity</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo></mrow><annotation encoding="application/x-tex">\le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span></span></span></span> 3000$</li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>key</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup></mrow><annotation encoding="application/x-tex">\le 10^4</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>value</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup></mrow><annotation encoding="application/x-tex">\le 10^5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span></span></span></span></li>
<li>最多调用 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>2</mn><mo>×</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup></mrow><annotation encoding="application/x-tex">2 \times 10^5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7278em;vertical-align:-0.0833em;"></span><span class="mord">2</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span></span></span></span> 次 <code>get</code> 和 <code>put</code></li>
</ul>
<h2 id="method-哈希表-双向链表"><a class="anchor" href="#method-哈希表-双向链表">#</a> Method: 哈希表 + 双向链表</h2>
<p>思路:</p>
<p>可以用一个哈希表和一个双向链表维护所有在 LRU 缓存中的键值对</p>
<ul>
<li>
<p>双向链表按照被使用的顺序存储键值对:靠近头部的键值对是最近使用的,而靠近尾部的键值对是最久未使用的</p>
</li>
<li>
<p>哈希表即为普通的哈希映射(HashMap),通过缓存数据的关键字 key 映射其在双向链表中的位置</p>
</li>
</ul>
<p>因此,我们可以先使用哈希表进行定位,找出缓存项在双向链表中的位置,随后将其移动到双向链表的头部,即可在 <code>O(1)</code> 的时间内完成 <code>get</code> 或者 <code>put</code> 操作</p>
<p>特别地,在双向链表的实现中,可以添加一个虚拟头部(dummy head)和虚拟尾部(dummy tail)。于是,添加节点和删除节点时,不需要再检查相邻的节点是否存在</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">struct</span> <span class="token class-name">DLinkedNode</span> <span class="token punctuation">{</span> <span class="token comment">// 双向链表</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token keyword">int</span> key<span class="token punctuation">,</span> value<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> DLinkedNode<span class="token operator">*</span> prev<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> DLinkedNode<span class="token operator">*</span> next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token function">DLinkedNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">key</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">value</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">prev</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token function">DLinkedNode</span><span class="token punctuation">(</span><span class="token keyword">int</span> _key<span class="token punctuation">,</span> <span class="token keyword">int</span> _value<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token function">key</span><span class="token punctuation">(</span>_key<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">value</span><span class="token punctuation">(</span>_value<span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">prev</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token function">next</span><span class="token punctuation">(</span><span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="7"></td><td><pre><span class="token punctuation">}</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="8"></td><td><pre></pre></td></tr><tr><td data-num="9"></td><td><pre><span class="token keyword">class</span> <span class="token class-name">LRUCache</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="10"></td><td><pre><span class="token keyword">private</span><span class="token operator">:</span></pre></td></tr><tr><td data-num="11"></td><td><pre> unordered_map<span class="token operator"><</span><span class="token keyword">int</span><span class="token punctuation">,</span> DLinkedNode<span class="token operator">*</span><span class="token operator">></span> hash<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> DLinkedNode<span class="token operator">*</span> head<span class="token punctuation">;</span> <span class="token comment">// 虚拟头节点</span></pre></td></tr><tr><td data-num="13"></td><td><pre> DLinkedNode<span class="token operator">*</span> tail<span class="token punctuation">;</span> <span class="token comment">// 虚拟尾节点</span></pre></td></tr><tr><td data-num="14"></td><td><pre> <span class="token keyword">int</span> _capacity<span class="token punctuation">;</span> <span class="token comment">// 缓存的容量</span></pre></td></tr><tr><td data-num="15"></td><td><pre> <span class="token keyword">int</span> _size<span class="token punctuation">;</span> <span class="token comment">// 当前占用的缓存大小</span></pre></td></tr><tr><td data-num="16"></td><td><pre></pre></td></tr><tr><td data-num="17"></td><td><pre><span class="token keyword">public</span><span class="token operator">:</span></pre></td></tr><tr><td data-num="18"></td><td><pre> <span class="token function">LRUCache</span><span class="token punctuation">(</span><span class="token keyword">int</span> capacity<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 初始化</span></pre></td></tr><tr><td data-num="19"></td><td><pre> head <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">DLinkedNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="20"></td><td><pre> tail <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">DLinkedNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="21"></td><td><pre> head<span class="token operator">-></span>next <span class="token operator">=</span> tail<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="22"></td><td><pre> tail<span class="token operator">-></span>prev <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="23"></td><td><pre> _size <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="24"></td><td><pre> _capacity <span class="token operator">=</span> capacity<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="25"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="26"></td><td><pre> </pre></td></tr><tr><td data-num="27"></td><td><pre> <span class="token keyword">int</span> <span class="token function">get</span><span class="token punctuation">(</span><span class="token keyword">int</span> key<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="28"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>hash<span class="token punctuation">.</span><span class="token function">count</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span> <span class="token comment">//key 不存在</span></pre></td></tr><tr><td data-num="29"></td><td><pre> DLinkedNode<span class="token operator">*</span> node <span class="token operator">=</span> hash<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">//key 已存在,先通过哈希表定位,再移到头部</span></pre></td></tr><tr><td data-num="30"></td><td><pre> <span class="token function">moveToHead</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="31"></td><td><pre> <span class="token keyword">return</span> node<span class="token operator">-></span>value<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="32"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="33"></td><td><pre> </pre></td></tr><tr><td data-num="34"></td><td><pre> <span class="token keyword">void</span> <span class="token function">put</span><span class="token punctuation">(</span><span class="token keyword">int</span> key<span class="token punctuation">,</span> <span class="token keyword">int</span> value<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="35"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>hash<span class="token punctuation">.</span><span class="token function">count</span><span class="token punctuation">(</span>key<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">//key 已存在,通过哈希表定位,修改数据值,并移到头部</span></pre></td></tr><tr><td data-num="36"></td><td><pre> DLinkedNode<span class="token operator">*</span> node <span class="token operator">=</span> hash<span class="token punctuation">[</span>key<span class="token punctuation">]</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="37"></td><td><pre> node<span class="token operator">-></span>value <span class="token operator">=</span> value<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="38"></td><td><pre> <span class="token function">moveToHead</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="39"></td><td><pre> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span> <span class="token comment">//key 不存在,创建一个新的节点,添加到链表头部,并建立哈希表索引</span></pre></td></tr><tr><td data-num="40"></td><td><pre> DLinkedNode<span class="token operator">*</span> node <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">DLinkedNode</span><span class="token punctuation">(</span>key<span class="token punctuation">,</span> value<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="41"></td><td><pre> <span class="token function">addToHead</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="42"></td><td><pre> hash<span class="token punctuation">[</span>key<span class="token punctuation">]</span> <span class="token operator">=</span> node<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="43"></td><td><pre> <span class="token operator">++</span>_size<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="44"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>_size <span class="token operator">></span> _capacity<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 超出容量,需删除最久未使用的关键字</span></pre></td></tr><tr><td data-num="45"></td><td><pre> DLinkedNode<span class="token operator">*</span> removed <span class="token operator">=</span> tail<span class="token operator">-></span>prev<span class="token punctuation">;</span> <span class="token comment">// 需移除的节点(即,虚拟尾节点的前一个节点)</span></pre></td></tr><tr><td data-num="46"></td><td><pre> <span class="token function">removeNode</span><span class="token punctuation">(</span>removed<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 从链表中移除</span></pre></td></tr><tr><td data-num="47"></td><td><pre> hash<span class="token punctuation">.</span><span class="token function">erase</span><span class="token punctuation">(</span>removed<span class="token operator">-></span>key<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 从哈希表中移除</span></pre></td></tr><tr><td data-num="48"></td><td><pre> <span class="token keyword">delete</span> removed<span class="token punctuation">;</span> <span class="token comment">// 从内存中删除</span></pre></td></tr><tr><td data-num="49"></td><td><pre> <span class="token operator">--</span>_size<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="50"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="51"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="52"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="53"></td><td><pre></pre></td></tr><tr><td data-num="54"></td><td><pre> <span class="token keyword">void</span> <span class="token function">removeNode</span><span class="token punctuation">(</span>DLinkedNode<span class="token operator">*</span> node<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 将 node 从链表中移除</span></pre></td></tr><tr><td data-num="55"></td><td><pre> node<span class="token operator">-></span>prev<span class="token operator">-></span>next <span class="token operator">=</span> node<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="56"></td><td><pre> node<span class="token operator">-></span>next<span class="token operator">-></span>prev <span class="token operator">=</span> node<span class="token operator">-></span>prev<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="57"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="58"></td><td><pre></pre></td></tr><tr><td data-num="59"></td><td><pre> <span class="token keyword">void</span> <span class="token function">addToHead</span><span class="token punctuation">(</span>DLinkedNode<span class="token operator">*</span> node<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 将 node 添加到链表头部</span></pre></td></tr><tr><td data-num="60"></td><td><pre> node<span class="token operator">-></span>prev <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="61"></td><td><pre> node<span class="token operator">-></span>next <span class="token operator">=</span> head<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="62"></td><td><pre> head<span class="token operator">-></span>next<span class="token operator">-></span>prev <span class="token operator">=</span> node<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="63"></td><td><pre> head<span class="token operator">-></span>next <span class="token operator">=</span> node<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="64"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="65"></td><td><pre></pre></td></tr><tr><td data-num="66"></td><td><pre> <span class="token keyword">void</span> <span class="token function">moveToHead</span><span class="token punctuation">(</span>DLinkedNode<span class="token operator">*</span> node<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 将 node 移至链表头部</span></pre></td></tr><tr><td data-num="67"></td><td><pre> <span class="token function">removeNode</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="68"></td><td><pre> <span class="token function">addToHead</span><span class="token punctuation">(</span>node<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="69"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="70"></td><td><pre><span class="token punctuation">}</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="71"></td><td><pre></pre></td></tr><tr><td data-num="72"></td><td><pre><span class="token comment">/**</span></pre></td></tr><tr><td data-num="73"></td><td><pre> * Your LRUCache object will be instantiated and called as such:</pre></td></tr><tr><td data-num="74"></td><td><pre> * LRUCache* obj = new LRUCache(capacity);</pre></td></tr><tr><td data-num="75"></td><td><pre> * int param_1 = obj->get(key);</pre></td></tr><tr><td data-num="76"></td><td><pre> * obj->put(key,value);</pre></td></tr><tr><td data-num="77"></td><td><pre> */</pre></td></tr></tbody></table></figure><p>参考:<a target="_blank" rel="noopener" href="https://leetcode.cn/problems/lru-cache/solution/lruhuan-cun-ji-zhi-by-leetcode-solution/">leetcode-solution</a></p>
<h1 id="leetcode-148-排序链表"><a class="anchor" href="#leetcode-148-排序链表">#</a> LeetCode 148. 排序链表</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode.cn/problems/sort-list/">148. Sort List</a></p>
<p>给你链表的头结点 <code>head</code> ,请将其按 <strong>升序</strong> 排列并返回 <strong>排序后的链表</strong> 。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode148_Example1.webp" alt="" height="150px"></p>
<pre><code>输入:head = [4,2,1,3]
输出:[1,2,3,4]
</code></pre>
<p><strong>示例 2:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode148_Example2.webp" alt="" height="150px"></p>
<pre><code>输入:head = [-1,5,3,4,0]
输出:[-1,0,3,4,5]
</code></pre>
<p><strong>示例 3:</strong></p>
<pre><code>输入:head = []
输出:[]
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li>链表中节点的数目范围为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>0</mn><mo separator="true">,</mo><mn>5</mn><mo>×</mo><mn>1</mn><msup><mn>0</mn><mn>4</mn></msup><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[0, 5 \times 10^4]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">0</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">5</span><span class="mspace" style="margin-right:0.2222em;"></span><span class="mbin">×</span><span class="mspace" style="margin-right:0.2222em;"></span></span><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">4</span></span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span></li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>−</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup><mo>≤</mo></mrow><annotation encoding="application/x-tex">-10^5 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.9501em;vertical-align:-0.136em;"></span><span class="mord">−</span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup></mrow><annotation encoding="application/x-tex">\le 10^5</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.8141em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span></span></span></span></li>
</ul>
<p><strong>进阶</strong>:你可以在 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mi>log</mi><mo></mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n \log n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span> 时间复杂度和常数级空间复杂度下,对链表进行排序吗?</p>
<h2 id="思路-7"><a class="anchor" href="#思路-7">#</a> 思路</h2>
<p>时间复杂度为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mi>log</mi><mo></mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n \log{n})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">n</span></span><span class="mclose">)</span></span></span></span> 的排序算法包括归并排序、堆排序和快速排序(快速排序的最差时间复杂度是 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><msup><mi>n</mi><mn>2</mn></msup><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n^2)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord"><span class="mord mathnormal">n</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">2</span></span></span></span></span></span></span></span><span class="mclose">)</span></span></span></span>)。其中,最适合链表的排序算法是归并排序</p>
<ul>
<li>考虑到递归调用的栈空间,自顶向下归并排序的空间复杂度为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo></mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\log{n})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">n</span></span><span class="mclose">)</span></span></span></span></li>
<li>自底向上归并排序的空间复杂度为 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></li>
</ul>
<h2 id="method-1-自顶向下归并排序"><a class="anchor" href="#method-1-自顶向下归并排序">#</a> Method 1: 自顶向下归并排序</h2>
<p>算法思路:</p>
<p>定义一个递归函数,用于实现对区间 [head, tail) 的归并排序</p>
<p>递归的终止条件:链表的节点个数小于或等于 1,无需再对链表进行拆分和排序,当前递归结束</p>
<ul>
<li>特别地,为便于后续进行归并,应将单个链表节点的 next 指针置为空(用于标记子链表的末尾)</li>
</ul>
<p>单层递归的逻辑:</p>
<ul>
<li>使用快慢指针找到链表的中点</li>
<li>以中点为分界,将链表拆分成两个子链表</li>
<li>对两个子链表分别排序</li>
<li>将两个排序后的子链表合并(归并)</li>
</ul>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">sortList</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token keyword">return</span> <span class="token function">mergeSort</span><span class="token punctuation">(</span>head<span class="token punctuation">,</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="4"></td><td><pre></pre></td></tr><tr><td data-num="5"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">mergeSort</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> tail<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 对区间 [head, tail) 进行归并排序</span></pre></td></tr><tr><td data-num="6"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>head <span class="token operator">==</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>head<span class="token operator">-></span>next <span class="token operator">==</span> tail<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="8"></td><td><pre> head<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="9"></td><td><pre> <span class="token keyword">return</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="11"></td><td><pre> ListNode<span class="token operator">*</span> fast <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> ListNode<span class="token operator">*</span> slow <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>fast <span class="token operator">!=</span> tail <span class="token operator">&&</span> fast<span class="token operator">-></span>next <span class="token operator">!=</span> tail<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 快慢指针,找出区间 [head, tail) 中点</span></pre></td></tr><tr><td data-num="14"></td><td><pre> fast <span class="token operator">=</span> fast<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> slow <span class="token operator">=</span> slow<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="17"></td><td><pre> ListNode<span class="token operator">*</span> list1 <span class="token operator">=</span> <span class="token function">mergeSort</span><span class="token punctuation">(</span>head<span class="token punctuation">,</span> slow<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 对区间 [head, slow) 进行归并排序</span></pre></td></tr><tr><td data-num="18"></td><td><pre> ListNode<span class="token operator">*</span> list2 <span class="token operator">=</span> <span class="token function">mergeSort</span><span class="token punctuation">(</span>slow<span class="token punctuation">,</span> tail<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 对区间 [slow, tail) 进行归并排序</span></pre></td></tr><tr><td data-num="19"></td><td><pre> <span class="token keyword">return</span> <span class="token function">merge</span><span class="token punctuation">(</span>list1<span class="token punctuation">,</span> list2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 归并</span></pre></td></tr><tr><td data-num="20"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="21"></td><td><pre></pre></td></tr><tr><td data-num="22"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">merge</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head1<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> head2<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 归并</span></pre></td></tr><tr><td data-num="23"></td><td><pre> ListNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="24"></td><td><pre> ListNode<span class="token operator">*</span> cur <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="25"></td><td><pre> ListNode<span class="token operator">*</span> temp1 <span class="token operator">=</span> head1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="26"></td><td><pre> ListNode<span class="token operator">*</span> temp2 <span class="token operator">=</span> head2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="27"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>temp1 <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> temp2 <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="28"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>temp1<span class="token operator">-></span>val <span class="token operator"><</span> temp2<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="29"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> temp1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="30"></td><td><pre> temp1 <span class="token operator">=</span> temp1<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="31"></td><td><pre> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="32"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> temp2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="33"></td><td><pre> temp2 <span class="token operator">=</span> temp2<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="34"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="35"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="36"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="37"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> temp1 <span class="token operator">==</span> <span class="token keyword">nullptr</span> <span class="token operator">?</span> temp2 <span class="token operator">:</span> temp1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="38"></td><td><pre> <span class="token keyword">return</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="39"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mi>log</mi><mo></mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n \log{n})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">n</span></span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 是链表的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>log</mi><mo></mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(\log{n})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">n</span></span><span class="mclose">)</span></span></span></span>,考虑了递归调用的栈空间</p>
<h2 id="method-2-自底向上归并排序"><a class="anchor" href="#method-2-自底向上归并排序">#</a> Method 2: 自底向上归并排序</h2>
<p>算法思路:</p>
<p>首先求得链表的长度 length,然后将链表拆分成子链表进行合并</p>
<ul>
<li>用 subLength 表示每次需要排序的子链表的长度,初始时 subLength = 1</li>
<li>将链表拆分成若干个长度为 subLength 的子链表(最后一个子链表的长度可以小于 subLength),按照每两个子链表一组进行归并</li>
<li>将 subLength 的值加倍,重复第 2 步,对更长的有序子链表进行归并,直到有序子链表的长度大于或等于 length,整个链表排序完毕</li>
</ul>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">sortList</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> <span class="token comment">// 计算链表长度</span></pre></td></tr><tr><td data-num="3"></td><td><pre> <span class="token keyword">int</span> length <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span>ListNode<span class="token operator">*</span> tmp <span class="token operator">=</span> head<span class="token punctuation">;</span> tmp <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> tmp <span class="token operator">=</span> tmp<span class="token operator">-></span>next<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="5"></td><td><pre> <span class="token operator">++</span>length<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre> </pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token comment">// 拆分链表</span></pre></td></tr><tr><td data-num="8"></td><td><pre> ListNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">,</span> head<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 虚拟头节点</span></pre></td></tr><tr><td data-num="9"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> subLength <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> subLength <span class="token operator"><</span> length<span class="token punctuation">;</span> subLength <span class="token operator">=</span> subLength <span class="token operator"><<</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 遍历每次排序的子链表的长度</span></pre></td></tr><tr><td data-num="10"></td><td><pre> ListNode<span class="token operator">*</span> prev <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span> <span class="token comment">// 指向已归并的子链表的末尾</span></pre></td></tr><tr><td data-num="11"></td><td><pre> ListNode<span class="token operator">*</span> cur <span class="token operator">=</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> <span class="token comment">// 按照每两个子链表一组进行合并</span></pre></td></tr><tr><td data-num="13"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>cur <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="14"></td><td><pre> ListNode<span class="token operator">*</span> head1 <span class="token operator">=</span> cur<span class="token punctuation">;</span> <span class="token comment">// 第一段子链表的头部</span></pre></td></tr><tr><td data-num="15"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><</span> subLength <span class="token operator">&&</span> cur<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> <span class="token operator">++</span>i<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="16"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="17"></td><td><pre> ListNode<span class="token operator">*</span> head2 <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">// 第二段子链表的头部</span></pre></td></tr><tr><td data-num="18"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> <span class="token comment">// 断开第一段子链表与第二段子链表</span></pre></td></tr><tr><td data-num="19"></td><td><pre> cur <span class="token operator">=</span> head2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="20"></td><td><pre> <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span> i <span class="token operator"><</span> subLength <span class="token operator">&&</span> cur <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> cur<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> <span class="token operator">++</span>i<span class="token punctuation">)</span></pre></td></tr><tr><td data-num="21"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="22"></td><td><pre> ListNode<span class="token operator">*</span> node <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="23"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>cur <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="24"></td><td><pre> node <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span> <span class="token comment">// 剩余链表的头部</span></pre></td></tr><tr><td data-num="25"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span> <span class="token comment">// 断开第二段子链表与剩余链表</span></pre></td></tr><tr><td data-num="26"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="27"></td><td><pre> ListNode<span class="token operator">*</span> merged <span class="token operator">=</span> <span class="token function">merge</span><span class="token punctuation">(</span>head1<span class="token punctuation">,</span> head2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 将第一段子链表与第二段子链表归并</span></pre></td></tr><tr><td data-num="28"></td><td><pre> prev<span class="token operator">-></span>next <span class="token operator">=</span> merged<span class="token punctuation">;</span> <span class="token comment">// 将归并完成的链表进行连接</span></pre></td></tr><tr><td data-num="29"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>prev<span class="token operator">-></span>next <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token comment">// 更新 prev</span></pre></td></tr><tr><td data-num="30"></td><td><pre> prev <span class="token operator">=</span> prev<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="31"></td><td><pre> cur <span class="token operator">=</span> node<span class="token punctuation">;</span> <span class="token comment">// 对剩余链表继续拆分(排序)</span></pre></td></tr><tr><td data-num="32"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="33"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="34"></td><td><pre> <span class="token keyword">return</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="35"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="36"></td><td><pre></pre></td></tr><tr><td data-num="37"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">merge</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head1<span class="token punctuation">,</span> ListNode<span class="token operator">*</span> head2<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 归并</span></pre></td></tr><tr><td data-num="38"></td><td><pre> ListNode<span class="token operator">*</span> dummyHead <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token function">ListNode</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="39"></td><td><pre> ListNode<span class="token operator">*</span> cur <span class="token operator">=</span> dummyHead<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="40"></td><td><pre> ListNode<span class="token operator">*</span> temp1 <span class="token operator">=</span> head1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="41"></td><td><pre> ListNode<span class="token operator">*</span> temp2 <span class="token operator">=</span> head2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="42"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>temp1 <span class="token operator">!=</span> <span class="token keyword">nullptr</span> <span class="token operator">&&</span> temp2 <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="43"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>temp1<span class="token operator">-></span>val <span class="token operator"><</span> temp2<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="44"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> temp1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="45"></td><td><pre> temp1 <span class="token operator">=</span> temp1<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="46"></td><td><pre> <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="47"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> temp2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="48"></td><td><pre> temp2 <span class="token operator">=</span> temp2<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="49"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="50"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="51"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="52"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>temp1 <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> cur<span class="token operator">-></span>next <span class="token operator">=</span> temp1<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="53"></td><td><pre> <span class="token keyword">else</span> cur<span class="token operator">-></span>next <span class="token operator">=</span> temp2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="54"></td><td><pre> <span class="token keyword">return</span> dummyHead<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="55"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mi>log</mi><mo></mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n \log{n})</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mop">lo<span style="margin-right:0.01389em;">g</span></span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord"><span class="mord mathnormal">n</span></span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 是链表的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<p>参考:<a target="_blank" rel="noopener" href="https://leetcode.cn/problems/sort-list/solution/pai-xu-lian-biao-by-leetcode-solution/">leetcode-solution</a></p>
<h1 id="leetcode-234-回文链表"><a class="anchor" href="#leetcode-234-回文链表">#</a> LeetCode 234. 回文链表</h1>
<p><a target="_blank" rel="noopener" href="https://leetcode.cn/problems/palindrome-linked-list/">234. Palindrome Linked List</a></p>
<p>给你一个单链表的头节点 <code>head</code> ,请你判断该链表是否为回文链表。如果是,返回 <code>true</code> ;否则,返回 <code>false</code> 。</p>
<p><strong>示例 1:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode234_Example1.webp" alt=""></p>
<pre><code>输入:head = [1,2,2,1]
输出:true
</code></pre>
<p><strong>示例 2:</strong></p>
<p><img loading="lazy" data-src="LeetCode-%E9%93%BE%E8%A1%A8%E4%B8%93%E9%A2%98/LeetCode234_Example2.webp" alt=""></p>
<pre><code>输入:head = [1,2]
输出:false
</code></pre>
<p><strong>提示:</strong></p>
<ul>
<li>链表中节点数目在范围 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">[</mo><mn>1</mn><mo separator="true">,</mo><mn>1</mn><msup><mn>0</mn><mn>5</mn></msup><mo stretchy="false">]</mo></mrow><annotation encoding="application/x-tex">[1, 10^5]</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1.0641em;vertical-align:-0.25em;"></span><span class="mopen">[</span><span class="mord">1</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.1667em;"></span><span class="mord">1</span><span class="mord"><span class="mord">0</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.8141em;"><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">5</span></span></span></span></span></span></span></span><span class="mclose">]</span></span></span></span> 内</li>
<li><span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mn>0</mn><mo>≤</mo></mrow><annotation encoding="application/x-tex">0 \le</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7804em;vertical-align:-0.136em;"></span><span class="mord">0</span><span class="mspace" style="margin-right:0.2778em;"></span><span class="mrel">≤</span></span></span></span> <code>Node.val</code> <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo>≤</mo><mn>9</mn></mrow><annotation encoding="application/x-tex">\le 9</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.7719em;vertical-align:-0.136em;"></span><span class="mrel">≤</span><span class="mspace" style="margin-right:0.2778em;"></span></span><span class="base"><span class="strut" style="height:0.6444em;"></span><span class="mord">9</span></span></span></span></li>
</ul>
<p><strong>进阶</strong>:你能否用 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span> 时间复杂度和 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span> 空间复杂度解决此题?</p>
<h2 id="method-1-栈"><a class="anchor" href="#method-1-栈">#</a> Method 1: 栈</h2>
<p>算法思路:先将所有链表节点入栈(栈具有先进后出的特点),然后将栈顶元素的值与原链表的值进行比较,并依次出栈</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre><span class="token keyword">bool</span> <span class="token function">isPalindrome</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="2"></td><td><pre> stack<span class="token operator"><</span>ListNode<span class="token operator">*</span><span class="token operator">></span> stk<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> cur <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>cur<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="5"></td><td><pre> stk<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>cur<span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="8"></td><td><pre> cur <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="9"></td><td><pre> ListNode<span class="token operator">*</span> tmp <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="10"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>cur<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="11"></td><td><pre> tmp <span class="token operator">=</span> stk<span class="token punctuation">.</span><span class="token function">top</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="12"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>tmp<span class="token operator">-></span>val <span class="token operator">!=</span> cur<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">false</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> stk<span class="token punctuation">.</span><span class="token function">pop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="14"></td><td><pre> cur <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="16"></td><td><pre> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="17"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 是链表的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span></p>
<h2 id="method-2-双指针"><a class="anchor" href="#method-2-双指针">#</a> Method 2: 双指针</h2>
<p>算法思路:</p>
<p>首先利用快慢指针找出链表的中间节点,将链表分割成两个子链表(如果链表节点数为奇数,则将中间节点划入第一个子链表)</p>
<ul>
<li>若链表节点数为奇数,快慢指针的最终位置应为:慢指针应指向正中间的节点,快指针指向最后一个节点</li>
<li>若链表节点数为奇数,快慢指针的最终位置应为:慢指针应指向左侧的中间节点,快指针指向倒数第二个节点</li>
<li>由此可推断出,移动快慢指针的条件为: <code>fast->next != nullptr && fast->next->next != nullptr</code></li>
</ul>
<p>然后反转第二个子链表,将第一个子链表与反转后的第二个子链表进行比较,若对应节点值相等,则原链表为回文链表,否则,原链表不是回文链表</p>
<p>最后,需要将链表恢复原样</p>
<p>代码实现:</p>
<figure class="highlight cpp"><figcaption data-lang="C++"></figcaption><table><tbody><tr><td data-num="1"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">findMidPoint</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 寻找链表的中间节点</span></pre></td></tr><tr><td data-num="2"></td><td><pre> ListNode<span class="token operator">*</span> fast <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="3"></td><td><pre> ListNode<span class="token operator">*</span> slow <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="4"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>fast<span class="token operator">-></span>next <span class="token operator">&&</span> fast<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 快指针移动到链表末尾,慢指针移动到链表中间</span></pre></td></tr><tr><td data-num="5"></td><td><pre> fast <span class="token operator">=</span> fast<span class="token operator">-></span>next<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="6"></td><td><pre> slow <span class="token operator">=</span> slow<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="7"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="8"></td><td><pre> <span class="token keyword">return</span> slow<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="9"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="10"></td><td><pre></pre></td></tr><tr><td data-num="11"></td><td><pre>ListNode<span class="token operator">*</span> <span class="token function">reverseLinkedList</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// 反转链表</span></pre></td></tr><tr><td data-num="12"></td><td><pre> ListNode<span class="token operator">*</span> pre <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="13"></td><td><pre> ListNode<span class="token operator">*</span> cur <span class="token operator">=</span> head<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="14"></td><td><pre> ListNode<span class="token operator">*</span> tmp <span class="token operator">=</span> <span class="token keyword">nullptr</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="15"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>cur<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="16"></td><td><pre> tmp <span class="token operator">=</span> cur<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="17"></td><td><pre> cur<span class="token operator">-></span>next <span class="token operator">=</span> pre<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="18"></td><td><pre> pre <span class="token operator">=</span> cur<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="19"></td><td><pre> cur <span class="token operator">=</span> tmp<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="20"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="21"></td><td><pre> <span class="token keyword">return</span> pre<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="22"></td><td><pre><span class="token punctuation">}</span></pre></td></tr><tr><td data-num="23"></td><td><pre></pre></td></tr><tr><td data-num="24"></td><td><pre><span class="token keyword">bool</span> <span class="token function">isPalindrome</span><span class="token punctuation">(</span>ListNode<span class="token operator">*</span> head<span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="25"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>head <span class="token operator">==</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token boolean">true</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="26"></td><td><pre> ListNode<span class="token operator">*</span> midpoint <span class="token operator">=</span> <span class="token function">findMidPoint</span><span class="token punctuation">(</span>head<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 链表的中间节点</span></pre></td></tr><tr><td data-num="27"></td><td><pre> ListNode<span class="token operator">*</span> temp1 <span class="token operator">=</span> head<span class="token punctuation">;</span> <span class="token comment">// 第一段子链表的头部</span></pre></td></tr><tr><td data-num="28"></td><td><pre> ListNode<span class="token operator">*</span> head2 <span class="token operator">=</span> <span class="token function">reverseLinkedList</span><span class="token punctuation">(</span>midpoint<span class="token operator">-></span>next<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 第二段子链表的头部</span></pre></td></tr><tr><td data-num="29"></td><td><pre> ListNode<span class="token operator">*</span> temp2 <span class="token operator">=</span> head2<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="30"></td><td><pre> <span class="token keyword">while</span> <span class="token punctuation">(</span>temp2 <span class="token operator">!=</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span> <span class="token punctuation">{</span></pre></td></tr><tr><td data-num="31"></td><td><pre> <span class="token keyword">if</span> <span class="token punctuation">(</span>temp1<span class="token operator">-></span>val <span class="token operator">!=</span> temp2<span class="token operator">-></span>val<span class="token punctuation">)</span> <span class="token keyword">break</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="32"></td><td><pre> temp1 <span class="token operator">=</span> temp1<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="33"></td><td><pre> temp2 <span class="token operator">=</span> temp2<span class="token operator">-></span>next<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="34"></td><td><pre> <span class="token punctuation">}</span></pre></td></tr><tr><td data-num="35"></td><td><pre> <span class="token keyword">bool</span> ans <span class="token operator">=</span> <span class="token punctuation">(</span>temp2 <span class="token operator">==</span> <span class="token keyword">nullptr</span><span class="token punctuation">)</span><span class="token punctuation">;</span></pre></td></tr><tr><td data-num="36"></td><td><pre> midpoint<span class="token operator">-></span>next <span class="token operator">=</span> <span class="token function">reverseLinkedList</span><span class="token punctuation">(</span>head2<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 还原链表</span></pre></td></tr><tr><td data-num="37"></td><td><pre> <span class="token keyword">return</span> ans<span class="token punctuation">;</span></pre></td></tr><tr><td data-num="38"></td><td><pre><span class="token punctuation">}</span></pre></td></tr></tbody></table></figure><p>时间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mi>n</mi><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(n)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord mathnormal">n</span><span class="mclose">)</span></span></span></span>,其中 <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>n</mi></mrow><annotation encoding="application/x-tex">n</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.4306em;"></span><span class="mord mathnormal">n</span></span></span></span> 是链表的长度</p>
<p>空间复杂度:<span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mi>O</mi><mo stretchy="false">(</mo><mn>1</mn><mo stretchy="false">)</mo></mrow><annotation encoding="application/x-tex">O(1)</annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathnormal" style="margin-right:0.02778em;">O</span><span class="mopen">(</span><span class="mord">1</span><span class="mclose">)</span></span></span></span></p>
<div class="tags"><a href="/tags/%E9%93%BE%E8%A1%A8/" rel="tag"><i class="ic i-tag"></i>链表</a></div></div><footer><div class="meta"><span class="item"><span class="icon"><i class="ic i-calendar-check"></i></span><span class="text">更新于</span><time title="修改时间:2024-06-08 23:08:58" itemprop="dateModified" datetime="2024-06-08T23:08:58+08:00">2024-06-08</time></span></div><div id="copyright"><ul><li class="author"><strong>本文作者:</strong>Jiankychen<i class="ic i-at"><em>@</em></i>Jiankychen's Blog</li><li class="link"><strong>本文链接:</strong><a href="https://jiankychen.github.io/leetcode-list.html" title="LeetCode - 链表专题">https://jiankychen.github.io/leetcode-list.html</a></li><li class="license"><strong>版权声明:</strong>本站所有文章除特别声明外,均采用 <a target="_blank" rel="noopener" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh"><i class="ic i-creative-commons"><em>(CC)</em></i>BY-NC-SA</a> 许可协议。转载请注明出处!</li></ul></div></footer></article></div><div class="post-nav"><div class="item left"><a href="/algorithm-complexity.html" rel="prev" itemprop="url" data-background-image="https://img.timelessq.com/images/2022/07/26/470d00578173666b5183f4631e51a421.jpg" title="算法复杂度"><span class="type">上一篇</span><span class="category"><i class="ic i-flag"></i>Data Structure</span><h3>算法复杂度</h3></a></div><div class="item right"><a href="/leetcode-vectors.html" rel="next" itemprop="url" data-background-image="https://i.imgtg.com/2023/03/09/Y0hOs.jpg" title="LeetCode - 数组专题"><span class="type">下一篇</span><span class="category"><i class="ic i-flag"></i>Coding</span><h3>LeetCode - 数组专题</h3></a></div></div><div class="wrap" id="comments"></div></div><div id="sidebar"><div class="inner"><div class="panels"><div class="inner"><div class="contents panel pjax" data-title="文章目录"><ol class="toc"><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-2-%E4%B8%A4%E6%95%B0%E7%9B%B8%E5%8A%A0"><span class="toc-number">1.</span> <span class="toc-text"> LeetCode 2. 两数相加</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%9D%E8%B7%AF"><span class="toc-number">1.1.</span> <span class="toc-text"> 思路</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-%E6%A8%A1%E6%8B%9F"><span class="toc-number">1.2.</span> <span class="toc-text"> Method: 模拟</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%86%99%E6%B3%95%E4%B8%80"><span class="toc-number">1.3.</span> <span class="toc-text"> 写法一</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#%E5%86%99%E6%B3%95%E4%BA%8C"><span class="toc-number">1.4.</span> <span class="toc-text"> 写法二</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-203-%E7%A7%BB%E9%99%A4%E9%93%BE%E8%A1%A8%E5%85%83%E7%B4%A0"><span class="toc-number">2.</span> <span class="toc-text"> LeetCode 203. 移除链表元素</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%9D%E8%B7%AF-2"><span class="toc-number">2.1.</span> <span class="toc-text"> 思路</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-1-%E7%9B%B4%E6%8E%A5%E4%BD%BF%E7%94%A8%E5%8E%9F%E9%93%BE%E8%A1%A8%E6%9D%A5%E8%BF%9B%E8%A1%8C%E5%88%A0%E9%99%A4%E6%93%8D%E4%BD%9C"><span class="toc-number">2.2.</span> <span class="toc-text"> Method 1: 直接使用原链表来进行删除操作</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-2-%E8%AE%BE%E7%BD%AE%E8%99%9A%E6%8B%9F%E5%A4%B4%E8%8A%82%E7%82%B9%E5%86%8D%E8%BF%9B%E8%A1%8C%E5%88%A0%E9%99%A4%E6%93%8D%E4%BD%9C"><span class="toc-number">2.3.</span> <span class="toc-text"> Method 2: 设置虚拟头节点再进行删除操作</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-707-%E8%AE%BE%E8%AE%A1%E9%93%BE%E8%A1%A8"><span class="toc-number">3.</span> <span class="toc-text"> LeetCode 707. 设计链表</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%9D%E8%B7%AF-3"><span class="toc-number">3.1.</span> <span class="toc-text"> 思路</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-%E5%8D%95%E9%93%BE%E8%A1%A8"><span class="toc-number">3.2.</span> <span class="toc-text"> Method: 单链表</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-876-%E9%93%BE%E8%A1%A8%E7%9A%84%E4%B8%AD%E9%97%B4%E7%BB%93%E7%82%B9"><span class="toc-number">4.</span> <span class="toc-text"> LeetCode 876. 链表的中间结点</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#method-1-%E6%95%B0%E7%BB%84"><span class="toc-number">4.1.</span> <span class="toc-text"> Method 1: 数组</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-2-%E5%8D%95%E6%8C%87%E9%92%88"><span class="toc-number">4.2.</span> <span class="toc-text"> Method 2: 单指针</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-3-%E5%BF%AB%E6%85%A2%E6%8C%87%E9%92%88"><span class="toc-number">4.3.</span> <span class="toc-text"> Method 3: 快慢指针</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-206-%E5%8F%8D%E8%BD%AC%E9%93%BE%E8%A1%A8"><span class="toc-number">5.</span> <span class="toc-text"> LeetCode 206. 反转链表</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#method-1-%E5%8F%8C%E6%8C%87%E9%92%88"><span class="toc-number">5.1.</span> <span class="toc-text"> Method 1: 双指针</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-2-%E9%80%92%E5%BD%92"><span class="toc-number">5.2.</span> <span class="toc-text"> Method 2: 递归</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-24-%E4%B8%A4%E4%B8%A4%E4%BA%A4%E6%8D%A2%E9%93%BE%E8%A1%A8%E4%B8%AD%E7%9A%84%E8%8A%82%E7%82%B9"><span class="toc-number">6.</span> <span class="toc-text"> LeetCode 24. 两两交换链表中的节点</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%9D%E8%B7%AF-4"><span class="toc-number">6.1.</span> <span class="toc-text"> 思路</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-%E5%8F%8C%E6%8C%87%E9%92%88"><span class="toc-number">6.2.</span> <span class="toc-text"> Method: 双指针</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-19-%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E7%9A%84%E5%80%92%E6%95%B0%E7%AC%AC-n-%E4%B8%AA%E7%BB%93%E7%82%B9"><span class="toc-number">7.</span> <span class="toc-text"> LeetCode 19. 删除链表的倒数第 N 个结点</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#method-%E5%8F%8C%E6%8C%87%E9%92%88-2"><span class="toc-number">7.1.</span> <span class="toc-text"> Method: 双指针</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-160-%E7%9B%B8%E4%BA%A4%E9%93%BE%E8%A1%A8"><span class="toc-number">8.</span> <span class="toc-text"> LeetCode 160. 相交链表</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%9D%E8%B7%AF-5"><span class="toc-number">8.1.</span> <span class="toc-text"> 思路</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-%E5%8F%8C%E6%8C%87%E9%92%88-3"><span class="toc-number">8.2.</span> <span class="toc-text"> Method: 双指针</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-141-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8"><span class="toc-number">9.</span> <span class="toc-text"> LeetCode 141. 环形链表</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#method-%E5%8F%8C%E6%8C%87%E9%92%88-4"><span class="toc-number">9.1.</span> <span class="toc-text"> Method: 双指针</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-142-%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8-ii"><span class="toc-number">10.</span> <span class="toc-text"> LeetCode 142. 环形链表 II</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%9D%E8%B7%AF-6"><span class="toc-number">10.1.</span> <span class="toc-text"> 思路</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-%E5%BF%AB%E6%85%A2%E6%8C%87%E9%92%88"><span class="toc-number">10.2.</span> <span class="toc-text"> Method: 快慢指针</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-21-%E5%90%88%E5%B9%B6%E4%B8%A4%E4%B8%AA%E6%9C%89%E5%BA%8F%E9%93%BE%E8%A1%A8"><span class="toc-number">11.</span> <span class="toc-text"> LeetCode 21. 合并两个有序链表</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#method-1-%E9%80%92%E5%BD%92"><span class="toc-number">11.1.</span> <span class="toc-text"> Method 1: 递归</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-2-%E8%BF%AD%E4%BB%A3"><span class="toc-number">11.2.</span> <span class="toc-text"> Method 2: 迭代</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-23-%E5%90%88%E5%B9%B6-k-%E4%B8%AA%E5%8D%87%E5%BA%8F%E9%93%BE%E8%A1%A8"><span class="toc-number">12.</span> <span class="toc-text"> LeetCode 23. 合并 K 个升序链表</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#method-1-%E9%A1%BA%E5%BA%8F%E5%90%88%E5%B9%B6"><span class="toc-number">12.1.</span> <span class="toc-text"> Method 1: 顺序合并</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-2-%E5%88%86%E6%B2%BB"><span class="toc-number">12.2.</span> <span class="toc-text"> Method 2: 分治</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#%E5%89%91%E6%8C%87-offer-06-%E4%BB%8E%E5%B0%BE%E5%88%B0%E5%A4%B4%E6%89%93%E5%8D%B0%E9%93%BE%E8%A1%A8"><span class="toc-number">13.</span> <span class="toc-text"> 剑指 Offer 06. 从尾到头打印链表</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#method-1-%E9%81%8D%E5%8E%86%E6%B7%BB%E5%8A%A0"><span class="toc-number">13.1.</span> <span class="toc-text"> Method 1: 遍历添加</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-2-%E9%80%92%E5%BD%92-2"><span class="toc-number">13.2.</span> <span class="toc-text"> Method 2: 递归</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-3-%E6%A0%88"><span class="toc-number">13.3.</span> <span class="toc-text"> Method 3: 栈</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-146-lru%E7%BC%93%E5%AD%98"><span class="toc-number">14.</span> <span class="toc-text"> LeetCode 146. LRU 缓存</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#method-%E5%93%88%E5%B8%8C%E8%A1%A8-%E5%8F%8C%E5%90%91%E9%93%BE%E8%A1%A8"><span class="toc-number">14.1.</span> <span class="toc-text"> Method: 哈希表 + 双向链表</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-148-%E6%8E%92%E5%BA%8F%E9%93%BE%E8%A1%A8"><span class="toc-number">15.</span> <span class="toc-text"> LeetCode 148. 排序链表</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#%E6%80%9D%E8%B7%AF-7"><span class="toc-number">15.1.</span> <span class="toc-text"> 思路</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-1-%E8%87%AA%E9%A1%B6%E5%90%91%E4%B8%8B%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F"><span class="toc-number">15.2.</span> <span class="toc-text"> Method 1: 自顶向下归并排序</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-2-%E8%87%AA%E5%BA%95%E5%90%91%E4%B8%8A%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F"><span class="toc-number">15.3.</span> <span class="toc-text"> Method 2: 自底向上归并排序</span></a></li></ol></li><li class="toc-item toc-level-1"><a class="toc-link" href="#leetcode-234-%E5%9B%9E%E6%96%87%E9%93%BE%E8%A1%A8"><span class="toc-number">16.</span> <span class="toc-text"> LeetCode 234. 回文链表</span></a><ol class="toc-child"><li class="toc-item toc-level-2"><a class="toc-link" href="#method-1-%E6%A0%88"><span class="toc-number">16.1.</span> <span class="toc-text"> Method 1: 栈</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#method-2-%E5%8F%8C%E6%8C%87%E9%92%88"><span class="toc-number">16.2.</span> <span class="toc-text"> Method 2: 双指针</span></a></li></ol></li></ol></div><div class="related panel pjax" data-title="系列文章"><ul><li><a href="/leetcode-binarysearch.html" rel="bookmark" title="LeetCode - 二分查找专题">LeetCode - 二分查找专题</a></li><li><a href="/leetcode-vectors.html" rel="bookmark" title="LeetCode - 数组专题">LeetCode - 数组专题</a></li><li class="active"><a href="/leetcode-list.html" rel="bookmark" title="LeetCode - 链表专题">LeetCode - 链表专题</a></li><li><a href="/leetcode-hashtable.html" rel="bookmark" title="LeetCode - 哈希表专题">LeetCode - 哈希表专题</a></li><li><a href="/leetcode-string.html" rel="bookmark" title="LeetCode - 字符串专题">LeetCode - 字符串专题</a></li><li><a href="/leetcode-stacks&queues.html" rel="bookmark" title="LeetCode - 栈与队列专题">LeetCode - 栈与队列专题</a></li><li><a href="/leetcode-binarytree.html" rel="bookmark" title="LeetCode - 二叉树专题">LeetCode - 二叉树专题</a></li><li><a href="/leetcode-traverse.html" rel="bookmark" title="LeetCode - 回溯专题">LeetCode - 回溯专题</a></li><li><a href="/leetcode-greedy.html" rel="bookmark" title="LeetCode - 贪心专题">LeetCode - 贪心专题</a></li><li><a href="/leetcode-dynamicprogramming.html" rel="bookmark" title="LeetCode - 动态规划专题">LeetCode - 动态规划专题</a></li><li><a href="/leetcode-doublepointer.html" rel="bookmark" title="LeetCode - 双指针专题">LeetCode - 双指针专题</a></li><li><a href="/leetcode-monotonicstacks.html" rel="bookmark" title="LeetCode - 单调栈专题">LeetCode - 单调栈专题</a></li><li><a href="/leetcode-search.html" rel="bookmark" title="LeetCode - 搜索专题">LeetCode - 搜索专题</a></li><li><a href="/leetcode-sort.html" rel="bookmark" title="LeetCode - 排序专题">LeetCode - 排序专题</a></li><li><a href="/leetcode-input&output.html" rel="bookmark" title="常见输入输出">常见输入输出</a></li><li><a href="/leetcode-analog.html" rel="bookmark" title="LeetCode - 模拟专题">LeetCode - 模拟专题</a></li></ul></div><div class="overview panel" data-title="站点概览"><div class="author" itemprop="author" itemscope="itemscope" itemtype="http://schema.org/Person"><img class="image" loading="lazy" decoding="async" itemprop="image" alt="Jiankychen" src="/assets/avatar.webp"><p class="name" itemprop="name">Jiankychen</p><div class="description" itemprop="description"></div></div><nav class="state"><div class="item posts"><a href="/archives/"><span class="count">51</span><span class="name">文章</span></a></div><div class="item categories"><a href="/categories/"><span class="count">8</span><span class="name">分类</span></a></div><div class="item tags"><a href="/tags/"><span class="count">20</span><span class="name">标签</span></a></div></nav><div class="social"><a target="_blank" rel="noopener" href="https://github.com/jiankychen" class="item github" title="https://github.com/jiankychen"><i class="ic i-github"></i></a><a href="mailto:[email protected]" class="item email" title="mailto:[email protected]"><i class="ic i-envelope"></i></a><a target="_blank" rel="noopener" href="https://music.163.com/#/user/home?id=447771275" class="item music" title="https://music.163.com/#/user/home?id=447771275"><i class="ic i-cloud-music"></i></a><a target="_blank" rel="noopener" href="https://www.zhihu.com/people/jiankychen" class="item zhihu" title="https://www.zhihu.com/people/jiankychen"><i class="ic i-zhihu"></i></a></div><div class="menu"><li class="item"><a href="/" rel="section"><i class="ic i-home"></i>首页</a></li><li class="item dropdown"><a href="#" onclick="return false;"><i class="ic i-feather"></i>文章</a><ul class="submenu"><li class="item"><a href="/archives/" rel="section"><i class="ic i-list-alt"></i>归档</a></li><li class="item"><a href="/categories/" rel="section"><i class="ic i-th"></i>分类</a></li><li class="item"><a href="/tags/" rel="section"><i class="ic i-tags"></i>标签</a></li></ul></li><li class="item dropdown"><a href="#" onclick="return false;"><i class="ic i-feather"></i>链接</a><ul class="submenu"><li class="item"><a href="/peers/" rel="section"><i class="ic i-magic"></i>链环</a></li><li class="item"><a href="/friends/" rel="section"><i class="ic i-heart"></i>友链</a></li></ul></li><li class="item dropdown"><a href="#" onclick="return false;"><i class="ic i-stars"></i>关于</a><ul class="submenu"><li class="item"><a href="/owner/" rel="section"><i class="ic i-user"></i>关于博主</a></li><li class="item"><a href="/site/" rel="section"><i class="ic i-paw"></i>关于本站</a></li><li class="item"><a href="/update/" rel="section"><i class="ic i-cloud"></i>更新日志</a></li></ul></li></div></div></div></div><ul id="quick"><li class="prev pjax"><a href="/leetcode-vectors.html" rel="prev" title="上一篇"><i class="ic i-chevron-left"></i></a></li><li class="up"><i class="ic i-arrow-up"></i></li><li class="down"><i class="ic i-arrow-down"></i></li><li class="next pjax"><a href="/algorithm-complexity.html" rel="next" title="下一篇"><i class="ic i-chevron-right"></i></a></li><li class="percent"></li></ul></div></div><div class="dimmer"></div></div></main><footer id="footer"><div class="inner"><div class="widgets"><div class="rpost pjax"><h2>随机文章</h2><ul><li class="item"><div class="breadcrumb"><a href="/categories/Data-Structure/" title="分类于Data Structure">Data Structure</a></div><span><a href="/KMP.html">KMP 算法</a></span></li><li class="item"><div class="breadcrumb"><a href="/categories/Data-Structure/" title="分类于Data Structure">Data Structure</a></div><span><a href="/dynamic-programming.html">动态规划</a></span></li><li class="item"><div class="breadcrumb"><a href="/categories/Coding/" title="分类于Coding">Coding</a></div><span><a href="/leetcode-monotonicstacks.html">LeetCode - 单调栈专题</a></span></li><li class="item"><div class="breadcrumb"><a href="/categories/Tutorial/" title="分类于Tutorial">Tutorial</a></div><span><a href="/vscode-intro.html">vscode 使用</a></span></li><li class="item"><div class="breadcrumb"><a href="/categories/C/" title="分类于C++">C++</a></div><span><a href="/cpp-vectors.html">C++ 字符串、向量和数组</a></span></li><li class="item"><div class="breadcrumb"><a href="/categories/Python/" title="分类于Python">Python</a></div><span><a href="/python-container.html">Python 数据容器</a></span></li><li class="item"><div class="breadcrumb"><a href="/categories/Tutorial/" title="分类于Tutorial">Tutorial</a><i class="ic i-angle-right"></i><a href="/categories/Tutorial/LaTeX/" title="分类于LaTeX">LaTeX</a></div><span><a href="/latex-to-word.html">LaTeX 转 Word</a></span></li><li class="item"><div class="breadcrumb"><a href="/categories/Coding/" title="分类于Coding">Coding</a></div><span><a href="/leetcode-sort.html">LeetCode - 排序专题</a></span></li><li class="item"><div class="breadcrumb"><a href="/categories/Data-Structure/" title="分类于Data Structure">Data Structure</a></div><span><a href="/binary-search.html">二分查找</a></span></li><li class="item"><div class="breadcrumb"><a href="/categories/Python/" title="分类于Python">Python</a></div><span><a href="/python-pandas.html">pandas 基础</a></span></li></ul></div><div class="rpost pjax"><h2>最新评论</h2><ul class="leancloud-recent-comment" id="new-comment"></ul></div></div><div class="status"><div class="copyright">© 2021 -<span itemprop="copyrightYear">2024</span><span class="with-love"><i class="ic i-sakura rotate"></i></span><span class="author" itemprop="copyrightHolder">Jiankychen @ Jiankychen</span></div><div class="count"><span class="post-meta-item-icon"><i class="ic i-chart-area"></i></span><span title="站点总字数">955k 字</span><span class="post-meta-divider"> | </span><span class="post-meta-item-icon"><i class="ic i-coffee"></i></span><span title="站点阅读时长">14:28</span></div><div class="powered-by">基于 <a target="_blank" rel="noopener" href="https://hexo.io/">Hexo</a> & Theme.<a target="_blank" rel="noopener" href="https://github.com/theme-shoka-x/hexo-theme-shokaX/">ShokaX</a></div></div><script src="https://unpkg.com/[email protected]/bsz.pure.mini.js"></script><div id="busuanzi-wrap"><span class="ic i-eye"></span><span id="busuanzi_container_site_pv">本站总访问量 <span id="busuanzi_value_site_pv"></span> 次</span> | <span class="ic i-user"></span><span id="busuanzi_container_site_uv">本站总访客量 <span id="busuanzi_value_site_uv"></span> 次</span></div></div></footer></div><script data-config="" type="text/javascript">var LOCAL = {
ispost: true,
path: `/leetcode-list`,
favicon: {
show: `Jiankychen`,
hide: `Jiankychen`
},
search: {
placeholder: "文章搜索",
empty: "关于 「 ${query} 」,什么也没搜到",
stats: "${time} ms 内找到 ${hits} 条结果"
},
copy_tex: true,
katex: true,
mermaid: false,
audio: undefined,
fancybox: true,
nocopy: false,
outime: true,
template: `<div class="note warning"><p><span class="label warning">文章时效性提示</span><br>这是一篇发布于 {{publish}} 天前,最后一次更新在 {{updated}} 天前的文章,部分信息可能已经发生改变,请注意甄别。</p></div>`,
quiz: {
choice: `单选题`,
multiple: `多选题`,
true_false: `判断题`,
essay: `问答题`,
gap_fill: `填空题`,
mistake: `错题备注`
},
ignores: [
(uri) => uri.includes('#'),
(uri) => new RegExp(LOCAL.path + '$').test(uri),
[]
]
};
</script><script src="https://lf9-cdn-tos.bytecdntp.com/cdn/expire-6-M/pace/1.2.4/pace.min.js" async=""></script><script src="https://polyfill.io/v3/polyfill.min.js?features=default,fetch" defer=""></script><script src="/js/siteInit.js?v=0.4.2" type="module" fetchpriority="high" defer=""></script></body></html>