-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlocal-search.xml
967 lines (462 loc) · 741 KB
/
local-search.xml
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
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>机器学习2021-GAN</title>
<link href="/2024/11/03/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-GAN/"/>
<url>/2024/11/03/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-GAN/</url>
<content type="html"><![CDATA[<h1 id="Generative-Model"><a href="#Generative-Model" class="headerlink" title="Generative Model"></a><strong>Generative Model</strong></h1><h3 id="1-Generative模型介绍"><a href="#1-Generative模型介绍" class="headerlink" title="1.Generative模型介绍"></a>1.Generative模型介绍</h3><ul><li>引入:将network当作一个生成器</li><li>输入是简单的distribution,经过network,输出复杂的distribution<ul><li>输入可以是一个已知的formulation,然后sample from it</li><li>为什么使用distribution?是为了输出的创造性,即当有相同的输入时可以有不同的输出</li></ul></li></ul><h3 id="2-GAN-生成式对抗模型"><a href="#2-GAN-生成式对抗模型" class="headerlink" title="2.GAN(生成式对抗模型)"></a>2.GAN(生成式对抗模型)</h3><ul><li>应用举例:动画人脸生成,先考虑unconditional gerneration</li><li>低维的输入通过Generator输出高维的向量,然后将输出交给另一个network(即Discriminator),输出一个scalar,数值越大表示输出越真</li><li>GAN的基本概念:<ul><li>生成器和判别器的对抗,二者不断进步</li></ul></li><li>算法:<ul><li>先初始化生成器和判别器</li><li>In each training iteration:<ul><li>step1:固定生成器,更新判别器(区分真实的和生成的)</li><li>step2:固定判别器,更新生成器(尝试骗过判别器)</li></ul></li></ul></li></ul><h3 id="3-GAN的原理"><a href="#3-GAN的原理" class="headerlink" title="3.GAN的原理"></a>3.GAN的原理</h3><ul><li><p>训练目标是什么:</p><ul><li>对于生成器,是找network里的一组参数,使得生成的数据和真实数据越相近越好</li><li>对于判别器,是找network里的一组参数,使得能够准确区分真实数据和生成的数据</li><li>数学表达:<ul><li>V(D,G) = E[log D(x)] + E[log(1-D(G(z)))]</li><li>其中D是判别器,G是生成器,x是真实数据,z是随机噪声</li><li>判别器D的目标是最大化V(D,G),生成器G的目标是最小化V(D,G)</li></ul></li><li>V(D,G) 本质上是一个negtive的交叉熵,相当于训练一个分类器</li></ul></li><li><p>GAN难以训练的问题:</p><ul><li>大部分情况下真实数据和生成数据几乎是不重叠的,(判别器)分类器可以很轻松的将其分开,此时,准确率或者说损失在GAN训练时是没有意义的。训练起来就很困难,需要在中途多次输出图片来查看效果</li></ul></li><li><p>解决:</p><ul><li><p>换一个衡量两个distribution的办法—WGAN:解决原始 GAN 训练不稳定和模式崩溃的问题</p></li><li><p>WGAN 使用 Wasserstein 距离来衡量真实数据分布和生成数据分布之间的差异,当真实数据和生成数据逐渐靠近时,Wasserstein距离也是逐渐变小的,便于训练</p></li><li><p>WGAN 如何解决 GAN 的问题:</p><ul><li>WGAN 的损失函数公式:</li></ul><figure class="highlight latex"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs latex">max(D属于1-lipschitz,足够平滑) = E[D(x)] - E[D(G(z))]<br></code></pre></td></tr></table></figure><ul><li>其中,D 是评论家(原判别器),G 是生成器,x 是真实数据样本,z 是随机噪声。WGAN 的目标是最小化这个 Wasserstein 距离。</li><li>提供了更稳定的梯度:Wasserstein 距离在整个样本空间中都是连续和可微的</li><li>减少模式崩溃:通过使用 Wasserstein 距离,WGAN 能够更好地捕捉整个数据分布,而不是只关注某些模式</li></ul></li><li><p>WGAN 的主要改进:</p><ul><li>将判别器替换为评论家(Critic),评论家<strong>不再输出概率,而是输出一个实数</strong></li><li>使用 Wasserstein 距离作为损失函数</li><li>对评论家的权重进行裁剪,以满足 Lipschitz 连续性条件</li></ul></li></ul><h3 id="4-Tips-for-GAN"><a href="#4-Tips-for-GAN" class="headerlink" title="4.Tips for GAN:"></a>4.Tips for GAN:</h3><ul><li>GAN在文字生成任务中的挑战:<ul><li>离散性:文本是离散的,而GAN通常用于生成连续数据(如图像)</li><li>梯度传播:由于文本的离散性,难以直接进行梯度反向传播</li><li>长期依赖:文本生成需要考虑长期依赖关系,而GAN通常擅长处理局部特征</li></ul></li><li>结合强化学习(RL)的优势:<ul><li>策略梯度:RL中的策略梯度方法可以处理离散输出</li><li>奖励机制:可以设计适合文本生成的奖励函数,如BLEU分数或语义相关性</li><li>序列决策:RL擅长处理序列决策问题,适合文本生成的特性</li></ul></li></ul><h3 id="5-GAN的评价指标"><a href="#5-GAN的评价指标" class="headerlink" title="5.GAN的评价指标"></a>5.GAN的评价指标</h3><ul><li>看一张图:通过一个影像辨识系统(Classifier),如果输出的概率分布比较集中,说明生成质量比较好<ul><li>问题1:Mode Collapse,多样性很差,生成的都是接近真实数据中少部分的数据</li><li>问题2:Mode Dropping,生成的数据都只是真实数据的一部分接近(比较难解决)</li></ul></li><li>看一堆图片:通过影像辨识系统,如果分布越平坦,表示多样性越好</li><li>指标:<ul><li>Inception Score (IS):<ul><li>衡量生成图像的质量和多样性</li><li>高IS表示生成的图像质量高且多样性好</li><li>缺点:不能很好地捕捉真实数据分布的特征,当都生成人脸,就难以判断多样性</li></ul></li><li>Fréchet Inception Distance (FID):<ul><li>拿出最后一层隐藏层输出的向量,来计算真实图像和生成图像在特征空间中的距离,较低的FID表示生成的图像更接近真实分布</li><li>优点:能更好地反映生成图像的质量和多样性,比如人脸数量的检测</li></ul></li></ul></li></ul><h3 id="6-Conditional-GAN"><a href="#6-Conditional-GAN" class="headerlink" title="6.Conditional GAN"></a>6.Conditional GAN</h3><ul><li>增加生成器的输入,多一个x</li><li>应用举例:Text to image的监督学习,x就是文字</li><li>训练:<ul><li>生成器:学习将输入的文本向量和随机噪声映射到图片空间</li><li>判别器:区分真实图像和生成图像,并判断图像是否符合输入的文本描述</li><li>损失函数:<ul><li>对抗损失:生成器试图生成判别器认为真实的图像,而判别器则试图将生成器生成的图像标记为假的。</li><li>条件匹配损失:用于确保生成图像和文本描述相符。</li></ul></li></ul></li></ul><h3 id="7-Cycle-GAN"><a href="#7-Cycle-GAN" class="headerlink" title="7.Cycle GAN"></a>7.Cycle GAN</h3><ul><li>无监督学习,没有匹配的数据</li><li>应用举例:图像风格迁移</li><li>核心思想:循环一致性<strong>(Cycle Consistency)</strong>。它使用了两个生成器和两个判别器来实现风格迁移,并保证转换前后的图像内容一致性。</li></ul><ol><li><p>生成器G和F</p><p>:CycleGAN包含两个生成器,分别用于实现不同风格的映射:</p><ul><li><strong>生成器 G</strong>:将图像从风格域X映射到风格域Y(例如,将普通照片转换为油画风格)。</li><li><strong>生成器 F</strong>:将图像从风格域Y映射回风格域X(例如,将油画风格图像转换回普通照片风格)。</li></ul></li><li><p>判别器DX和DY</p><p>:CycleGAN还包含两个判别器:</p><ul><li><strong>判别器 DX</strong>:用于判断图像是否属于风格域X(即区分普通照片和生成的照片)。</li><li><strong>判别器 DY</strong>:用于判断图像是否属于风格域Y(即区分真实油画风格图像和生成的油画风格图像)。</li></ul></li></ol><ul><li>其他应用:<ul><li>文字风格转换,无监督的摘要,翻译,语音转文字</li></ul></li></ul></li></ul>]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>笔记</tag>
</tags>
</entry>
<entry>
<title>机器学习2021-Transformer</title>
<link href="/2024/10/27/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-Transformer/"/>
<url>/2024/10/27/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-Transformer/</url>
<content type="html"><![CDATA[<h1 id="Transformer"><a href="#Transformer" class="headerlink" title="Transformer"></a><strong>Transformer</strong></h1><p>sequence-to-sequence model,输入和输出的长度没有固定关系</p><h3 id="应用:"><a href="#应用:" class="headerlink" title="应用:"></a>应用:</h3><ul><li>Speech Recognition</li><li>Machine Translation</li><li>Speech Translation</li><li>Text-to-Speech</li><li>chatbot,question+context—>seq2seq—>answer</li><li>syntactic parsing(文法剖析)</li><li>muti-label classification:同个东西可以属于多个classes,机器自己决定output sequence的长度</li><li>Object Detection(框出图片中的物件)</li></ul><h3 id="实现:"><a href="#实现:" class="headerlink" title="实现:"></a>实现:</h3><ul><li>Input sequence—><strong>Encoder</strong>—><strong>Decoder</strong>—>output sequence</li></ul><h3 id="Encoder"><a href="#Encoder" class="headerlink" title="Encoder:"></a>Encoder:</h3><p>给一排向量,输出一排向量</p><p>RNN,CNN都可以做到,但Transformer’s Encoder是self-attention</p><ul><li><p>内部架构:</p><ul><li><p>结构:</p></li><li><p>这里的<strong>Add&Norm</strong>指的是Residual+Layer Normalization</p></li><li><p>因为self-attention是不包含位置信息的,所以要另外增加一个<strong>positional encoding</strong></p></li><li><p><strong>Input Embedding</strong>的作用是将离散的符号转换为可以用于模型处理的连续数值向量</p></li><li><p><strong>multi-head attention</strong> 是对 self-attention 的扩展和增强,使得模型能够捕捉到<strong>不同类型的特征和关系</strong></p></li><li><p>里面有n个Block</p></li><li><p>Block里又有多层layer,做self-attention</p></li><li><p>self-attetion的输出会和输入做一个<strong>residual connection</strong></p></li><li><p>再做一个<strong>layer normalization</strong>,对同一个feature同一个example的不同dimension去计算μ和σ</p></li></ul></li></ul><h3 id="Decoder-Autoregressive-AT"><a href="#Decoder-Autoregressive-AT" class="headerlink" title="Decoder:Autoregressive(AT)"></a>Decoder:Autoregressive(AT)</h3><p>例子:语音识别</p><ul><li>结构:<ul><li>接收Encoder和向量输入,产生一个概率的distribution,再取max</li><li>内部结构中的self-attetion—>masked self-attention,因为Decoder是逐个产生输出的,不是一次性的输入,所以需要masked</li><li>增加END这一特殊符号来表示输出停止</li></ul></li><li>NAT:<ul><li>如何决定NAT的输出长度?<ul><li>用另外一个predictor进行预测</li><li>输出一个非常长的结果,不看END后的内容</li></ul></li><li>优势:是parallel的,速度快,并且可以控制输出长度</li><li>劣势:效果不如AT</li></ul></li></ul><h3 id="Encoder-Decoder"><a href="#Encoder-Decoder" class="headerlink" title="Encoder-Decoder:"></a>Encoder-Decoder:</h3><ul><li><p>Cross-Attention:</p><ul><li><p>原始情况:把Encoder最后一层输出交给Decoder作为输入。实际上,也可以把Encoder的中间层输出当作Decoder的输入。</p></li><li><p>作用:Decoder在生成每个输出时参考Encoder的输出序列(输入序列的编码信息),从而结合两个不同序列的信息生成更准确的输出</p></li><li><p>举例说明:在机器翻译任务中:</p><ul><li><strong>Encoder</strong> 对源语言(例如:“I love apples”)进行编码,得到每个词的向量表示。</li><li><strong>Decoder</strong> 在生成目标语言时,例如在生成“我爱苹果”中的“苹果”时,Decoder不仅会参考之前生成的词“我爱”,还会通过cross attention查阅Encoder对“apples”的编码,从而生成对应的目标词“苹果”。</li></ul></li></ul></li></ul><h3 id="Training"><a href="#Training" class="headerlink" title="Training:"></a>Training:</h3><ul><li><strong>Teacher force</strong>: using the ground truth as input<ul><li>输出做minimize cross entropy</li></ul></li></ul><h3 id="Tips"><a href="#Tips" class="headerlink" title="Tips:"></a>Tips:</h3><ul><li>Copy Machanism:<ul><li>Decoder不需要完全创造输出,可以从输入里复制部分内容作为输出</li><li>例如chat-bot,摘要</li></ul></li><li>Guided Attention:<ul><li>通常通过加入一个额外的损失项来实现,这个损失项迫使模型的注意力权重矩阵朝着一个目标结构分布</li><li>增强对齐能力,应用于机器翻译或语音合成</li></ul></li><li>Beam Search:<ul><li>核心思想是在每一步生成时,保留固定数量的最有希望的候选路径。然后,继续在这些候选路径的基础上生成下一个单词。</li><li>可以避免因局部决策错误导致生成整体质量下降的问题。</li><li>应用:机器翻译,文本生成,语音识别</li></ul></li><li>Sampling:<ul><li>在序列生成任务中,模型通常会为每个生成步骤输出一个概率分布(如词汇表中每个单词的概率)。<strong>Sampling</strong>的过程就是根据这个概率分布进行随机采样,而不是总是选择最可能的(即最高概率)的输出。</li><li>避免模型太确定,生成多样化的输出</li><li>应用:对话生成,文本生成,开放域生成任务</li></ul></li><li>Optimizing Evaluation Metrics(优化评估指标):<ul><li>评估指标衡量的是<strong>生成序列与参考序列之间的相似度或准确性</strong>,但它们往往是离散的,不可微分,不能直接用于模型的损失函数计算。评估指标如 BLEU 和 ROUGE 更关注生成的语义准确性和句子的连贯性。</li><li>所以往往采取RL(强化学习)来优化指标</li></ul></li><li>Scheduled Sampling<ul><li>在模型训练期间,模型总是使用真实的目标序列作为输入,但在推理阶段,模型必须依赖自己生成的输出作为后续步骤的输入。这种训练和测试的不一致叫做:<strong>Exposure bias</strong>。</li><li>核心思想是在训练过程中,逐渐将<strong>模型自身生成的输出</strong>与<strong>真实的目标序列</strong>混合,作为下一步的输入。从而,模型可以更好地适应推理阶段的生成方式,缓解<strong>Exposure bias。</strong></li></ul></li></ul>]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>笔记</tag>
</tags>
</entry>
<entry>
<title>机器学习2021-CNN+Self-Attention</title>
<link href="/2024/10/11/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-CNN-Self-Attention/"/>
<url>/2024/10/11/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-CNN-Self-Attention/</url>
<content type="html"><![CDATA[<h1 id="CNN-Self-Attention"><a href="#CNN-Self-Attention" class="headerlink" title="CNN & Self-Attention"></a><strong>CNN & Self-Attention</strong></h1><h2 id="Convolutional-Neural-Network-CNN"><a href="#Convolutional-Neural-Network-CNN" class="headerlink" title="Convolutional Neural Network(CNN)"></a>Convolutional Neural Network(CNN)</h2><p>专门用于影像处理</p><h3 id="引入:Image-classification"><a href="#引入:Image-classification" class="headerlink" title="引入:Image classification"></a>引入:Image classification</h3><ul><li>一张100<em>100的RGB图片,可以看作3</em>100*100,分别是channel,高,宽。</li><li>按照之前的想法,使用全连接网络,feature有3<em>100</em>100,假设sigmoid有100个,那么参数w将达到3*10^7个,参数越多,意味着模型越有弹性,但训练成本也会越高,越容易overfitting</li></ul><h3 id="Observation-1"><a href="#Observation-1" class="headerlink" title="Observation 1:"></a>Observation 1:</h3><ul><li>Identify some critical patterns,做图像分类时,只需要侦测到重要的pattern即可,不需要看整张图片</li></ul><h3 id="Simplification-1"><a href="#Simplification-1" class="headerlink" title="Simplification 1:"></a>Simplification 1:</h3><ul><li>划分receptive field,每个neuron只对一个receptive field的范围负责,并且receptive field彼此之间是可以有重叠,且同个范围可以有多个neuron负责</li><li>typical setting:<ul><li>all channels</li><li>kernel size: 3x3</li><li>Each receptive field has a set of neurons(e.g. 64)</li><li>stride=1 or 2</li><li>超出影像范围时进行padding(补零或是其他)</li><li>the receptive fields cover the whole image</li></ul></li></ul><h3 id="Observation-2"><a href="#Observation-2" class="headerlink" title="Observation 2:"></a>Observation 2:</h3><ul><li>The same patterns appear in different region,相同的pattern可能会出现在图像上不同的位置</li></ul><h3 id="Simplification-2"><a href="#Simplification-2" class="headerlink" title="Simplification 2:"></a>Simplification 2:</h3><ul><li>让不同receptive field的neuron共享参数,parameter sharing,即它们的weight是相同的</li><li>typical setting:<ul><li>每个receptive field都有64个neuron侦测,即一组参数Filter1,Filter2,…,共享的参数就是这些filter,即对应不同receptive field的neuron的weight完全相同</li></ul></li></ul><h3 id="小节:"><a href="#小节:" class="headerlink" title="小节:"></a>小节:</h3><ul><li>最开始是fully connected network,然后划分多个receptive field,每个neuron不用看整张图片,再然后neuron之间可以共享参数,整个model bias是不断增加的,对模型的限制也是增加的。</li><li>补充:共享参数也可以理解为一个filter扫过整张图片</li></ul><h3 id="Observation-3"><a href="#Observation-3" class="headerlink" title="Observation 3:"></a>Observation 3:</h3><ul><li>Subsampling the pixels will not change the object,当缩小图片时,不会影响图像识别</li></ul><h3 id="Simplification-3"><a href="#Simplification-3" class="headerlink" title="Simplification 3:"></a>Simplification 3:</h3><ul><li>pooling:把图片变小,可以有效减少运算量。对细微的检测可能会有影响,所以不一定会使用。</li></ul><h3 id="The-whole-CNN"><a href="#The-whole-CNN" class="headerlink" title="The whole CNN:"></a>The whole CNN:</h3><p><strong>Image=⇒Convolution=⇒Pooling=⇒Convolution=⇒Pooling=⇒Flatten=⇒Fully Connected Layers=⇒softmax=⇒result</strong></p><ul><li>补充:CNN不适用于scaling和rotation, need data augmentation</li></ul><h2 id="Self-attention"><a href="#Self-attention" class="headerlink" title="Self-attention"></a>Self-attention</h2><h3 id="引入:"><a href="#引入:" class="headerlink" title="引入:"></a>引入:</h3><ul><li>之前的问题都是基于输入是a vector,并且输出是a scalar or a class。那么,当输入是a set of vectors(sequence)且长度不固定,而输出是scalars或classes时,问题该如何解决呢?</li><li>vector set as input举例:<ul><li>句子输入,每个词汇是一个向量,句子就是多个长度不一的向量</li><li>语音输入,每个frame对应一个向量</li><li>Graph,每个node对应一个向量</li></ul></li><li>输出方式:<ul><li>每个vector对应有一个label,例如词性标注</li><li>The whole sequence has a label,只有一个输出</li><li>模型自定义label的数量</li></ul></li><li>针对第一种情况:每个vector对应有一个label,例如sequence labeling<ul><li>fully-connected可以考虑一个window里的上下文,但始终是有极限的,如何才能考虑整个sequence呢?</li><li>这就是self-attention可以解决的问题</li></ul></li></ul><h3 id="实现细节:"><a href="#实现细节:" class="headerlink" title="实现细节:"></a>实现细节:</h3><ul><li>输入时input或者是a hidden layer,self-attention 可以和fully-connected交替使用</li><li>针对每个输入向量ai,通过和对应的Wq,Wk,Wv矩阵相乘,有对应的q,k,v向量,每个qi和所有的ki进行dot-product(表示两个向量间的关联程度),再和分别所有的vi相乘在相加得到bi。每一个bi都按照这样的方式得出,就是self-attention所做的事情。所有的bi是同时计算的,是<strong>parallel</strong>的</li><li>进阶版本Multi-head self-attention:<ul><li>当有different type of relevance时,可以控制产生多种不同的q,k,v,最后再乘以一个矩阵来得到bi</li></ul></li><li>Positional Encoding:<ul><li>self-attention里本身是没有位置信息的</li><li>可以为每个position人为设置一个unique positional vector ei</li></ul></li></ul><h3 id="Application"><a href="#Application" class="headerlink" title="Application:"></a>Application:</h3><ul><li>Transfomer</li><li>Bert(NLP)</li><li>Speech</li><li>Image</li></ul><h3 id="Self-attention-vs-CNN"><a href="#Self-attention-vs-CNN" class="headerlink" title="Self-attention vs CNN:"></a>Self-attention vs CNN:</h3><ul><li>CNN可以看作是简化版的self-attention。而self-attention是复杂化的CNN,可以看作是自己学出来receptive field。</li><li>self-attention is good for more data,而CNN is good for less data</li></ul><h3 id="Self-attention-vs-RNN"><a href="#Self-attention-vs-RNN" class="headerlink" title="Self-attention vs RNN:"></a>Self-attention vs RNN:</h3><p>目前使用RNN的应用基本逐渐都被self-attention取代了</p><ul><li>RNN对于最右边的输出要考虑最左边的输入是很困难的,除非该信息一直存在memory里</li><li>而对于self-attention只需把对应的query和key进行match相乘即可得到(天涯若比例)</li><li>RNN是nonparallel的</li><li>self-attention是parallel的,效率更高</li></ul><p>self-attention特点:运算量比较大,相当于广义的transformer</p>]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>笔记</tag>
</tags>
</entry>
<entry>
<title>机器学习2021-Deep-Learning</title>
<link href="/2024/10/11/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-Deep-Learning/"/>
<url>/2024/10/11/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-Deep-Learning/</url>
<content type="html"><![CDATA[<h1 id="Deep-Learning"><a href="#Deep-Learning" class="headerlink" title="Deep Learning"></a><strong>Deep Learning</strong></h1><h3 id="1、General-Guidance"><a href="#1、General-Guidance" class="headerlink" title="1、General Guidance"></a>1、General Guidance</h3><h3 id="总结:"><a href="#总结:" class="headerlink" title="总结:"></a>总结:</h3><ul><li><p>1、并不是所有的在测试集上表现结果差都是overfitting,要先看在training data上的los怎么样?</p><ul><li>large:<ul><li>model bias(模型的限制)——>增加模型的复杂程度,function的范围</li><li>optimize(局部最优解)——>增加找function的力度</li></ul></li><li>small:<ul><li>loss on testing data<ul><li>large: overfitting<ul><li>more train</li><li>data augmentaion</li><li>make model simpler</li></ul></li><li>small: 😀</li></ul></li></ul></li><li>可视化:<ul><li><strong>当模型的复杂度增加,training loss会越来越小,但是testing loss会先减少后又增大</strong></li><li>这时候考虑overfitting或mismatch</li></ul></li><li>Optimization Issue<ul><li>先从简单的模型开始,容易optimization</li><li>当deeper network不能获得smaller loss on training data⇒Optimization Issue</li></ul></li></ul></li><li><p>2、有的时候在public的测试数据上结果很好,但是在pivate的数据上测试就不行了,主要还是因为可能测试次数过多,模型就会过于依赖public的数据,在实际的情况下效果反而打折扣</p><ul><li><p>solution:</p><p>N-fold cross validation</p><ul><li>将training set 等价划分为三份三次,其中一份用于validation,每次的位置不同</li><li>不同模型对这三次操作,结果取平均值,再用结果最好的模型去测Testing data</li></ul></li></ul></li></ul><h3 id="2、When-Gradient-Is-Small-Local-Minimum-and-Saddle-Point"><a href="#2、When-Gradient-Is-Small-Local-Minimum-and-Saddle-Point" class="headerlink" title="2、When Gradient Is Small: Local Minimum and Saddle Point"></a>2、When Gradient Is Small: Local Minimum and Saddle Point</h3><h3 id="Optimization-fails"><a href="#Optimization-fails" class="headerlink" title="Optimization fails:"></a>Optimization fails:</h3><ul><li><p>分析:loss not small enough</p><ul><li><p>gradient=0,所以导致了优化停止,一般有两种情况,统称为</p><p>critical point:</p><ul><li><strong>local minima</strong></li></ul></li></ul></li><li><p><strong>saddle point</strong></p><ul><li><p>Which one would be?</p><ul><li>使用Taler Series Approximation:用当前点来表示估计周围点</li></ul></li><li><p>总之,可以根据周围点的状态来判断当前的点是local minima, local maxima还是saddle point</p><ul><li>涉及到eigen value,eigen vector⇒计算量较大,实际不使用这种方法</li></ul></li></ul></li><li><p>local minima Vs saddle point</p><ul><li>一维的local minima在二维来看就是saddle point</li><li>一般训练的参数有百万千万,那么维度也非常的高,所以大多为saddle point,<strong>local minima很不常见</strong></li></ul></li></ul><h3 id="3、Tips-for-Training-Batch-and-Momentum"><a href="#3、Tips-for-Training-Batch-and-Momentum" class="headerlink" title="3、Tips for Training: Batch and Momentum"></a>3、Tips for Training: Batch and Momentum</h3><h3 id="batch"><a href="#batch" class="headerlink" title="batch:"></a>batch:</h3><ul><li>定义:将所有参数进行划分为多个batch,多次update来完成所有参数的更新gradient</li></ul><table><thead><tr><th></th><th>Small Batch</th><th>Large Batch</th><th>desc</th></tr></thead><tbody><tr><td>Speed for one update(no parallel)</td><td>Faster</td><td>Slower</td><td></td></tr><tr><td>Speed for one update(with parallel)</td><td>Same</td><td>Same(not too large)</td><td></td></tr><tr><td>Time for one epoch</td><td>Slower</td><td><strong><code>Faster</code></strong></td><td>训练速度更快</td></tr><tr><td>Gradient</td><td>Noisy</td><td>Stable</td><td></td></tr><tr><td>Optimization(training)</td><td><strong><code>Better</code></strong></td><td>Worse</td><td></td></tr><tr><td>Generalization(testing)</td><td><strong><code>Better</code></strong></td><td></td><td></td></tr></tbody></table><p>Small Batch更容易进入flat minima,而large Batch更容易进入有sharp minima。 | Worse</p><p>当在training上两者效果类似,但是在testing上不一样,就有overfitting的因素了。 | |</p><h3 id="Momentum"><a href="#Momentum" class="headerlink" title="Momentum:"></a>Momentum:</h3><ul><li>参照物理世界,一个小球从高处滚下来,很可能因为惯性逃脱critical point</li><li>一般的gradient descent:往Gradient的反方向移动</li><li>所以可以给每次movement增加一个movement of last step<ul><li>movement = movement of last step - gadient</li><li>或者可以理解为movement是之前所有gradient的一个加权和</li></ul></li></ul><h3 id="总结:2和3—Optimization-issue"><a href="#总结:2和3—Optimization-issue" class="headerlink" title="总结:2和3—Optimization issue"></a>总结:2和3—Optimization issue</h3><ul><li>训练停止处的critical points处gradient=0</li><li>critical points有两种情况:saddle points or local minima<ul><li>具体是哪一种可以由Hessian matrix判断</li><li>也可以通过Hessian matrix来逃离saddle points</li><li>local minima is rare</li></ul></li><li>Smaller batch size and momentum help escape critical points</li></ul><h3 id="4、Tips-for-Training-Adaptive-Learning-Rate"><a href="#4、Tips-for-Training-Adaptive-Learning-Rate" class="headerlink" title="4、Tips for Training: Adaptive Learning Rate"></a>4、Tips for Training: Adaptive Learning Rate</h3><ul><li><p>首先,Training stuck 不等于Small Gadient(可能是在一个很陡峭的峡谷里来回碰撞,到不了谷底)</p></li><li><p>多数training在走到critical point之前就已经停止了</p></li><li><p>这时候考虑learning rate,即update的步长</p><ul><li>gradient越小,表示越平滑,lr可以大一点;</li><li>gradient越大,表示越陡峭,lr可以小一点;</li><li>单纯地调小learning rate并不能解决问题,因为可能步长太小而一直无法到达</li></ul></li><li><p>所以,需要动态地修改学习率:</p><ul><li><p>增加分母:</p><ul><li>Root Mean Sequare:和之前所有的g都有关系,lr会随着时间的增长而变小 ,是所有之前的g的均方开根号<ul><li>局限:就算同一个参数,它需要的lr也会发生变化</li></ul></li><li>引出RMS Prop:σ_i^t = ρσ_i^{t-1} + (1-ρ)(g_i^t)^2<ul><li>决定当前算出来的g有多重要</li></ul></li><li>最常用的optimization策略:Adam:RMS Prop + Momentum</li></ul></li><li><p>修改分子:</p><ul><li><p>使用Root Mean Sequare在一段时间后,一直往同一个方向走,它垂直方向的学习率会变大,会突然爆发,虽然最后会回归</p></li><li><p>引入learning rate scheduling, 让原先的常数随着时间变化而变化,可以解决爆发的问题</p><ul><li>Learning Rate Decay:从一个高值开始逐渐减少</li><li>Warm up:先增加后减小</li></ul></li></ul></li></ul></li><li><p>总结:**<code>learning rate improvement+ momentum</code>**</p></li></ul><h3 id="5、Loss-Function-Classification"><a href="#5、Loss-Function-Classification" class="headerlink" title="5、Loss Function: Classification"></a>5、Loss Function: Classification</h3><ul><li>原先的regression的输出是一个数值,在此基础上进行修改,最后几个步骤也要扩展为向量操作</li><li>得到的y要先经过sotfmax做规范化,把数值的范围变成0-1</li><li>再计算e,就是y和y_hat之间的距离<ul><li>MSE</li><li><strong><code>Cross-entropy</code> 效果更好</strong></li><li>说明:改变loss function 也会改变optimization的难度</li></ul></li></ul><h3 id="6、Batch-Normalization-(optimization-tips)"><a href="#6、Batch-Normalization-(optimization-tips)" class="headerlink" title="6、Batch Normalization (optimization tips)"></a>6、Batch Normalization (optimization tips)</h3><p><a href="https://www.youtube.com/watch?v=BABPWOkSbLE">https://www.youtube.com/watch?v=BABPWOkSbLE</a></p><ul><li>背景:<ul><li>当只有两个dimension时,loss的error surface是一个碗型(椭圆形)的,training可能还是不好做,会发生梯度爆炸的情况,体现在一个w对loss的影响大,而另一个很小。那么是否可以改变error surface的形状,变成一个很正的一个个圆形</li></ul></li><li>分析:<ul><li>再往里想一层,就是input的feature,每个dimension的值的scale差距比较大,导致了training的不容易</li></ul></li><li>引出:<ul><li>对feature进行一个normalization,把数值的范围进行一个规范化,可以使梯度下降的速度更快</li><li>Deep Learning:除了对输入进行normalization,可以在中间层进行多次的normalization,实际操作过程中是分batch进行的所以称作<strong>batch normalization</strong>。</li></ul></li><li>testing:<ul><li>在测试或是实际应用的不是,不能等到集齐一个batch size再进行计算,所以实际pytorch会在training的时候计算moving average of U and 6,在testing的时候可以直接使用,那么每笔新的资料进来都可以直接做一次运算。</li></ul></li><li>效果:<ul><li>使用了batch normalization后,可以在更短的时间内到达一样的正确率,并且,使用了normalization后,learning rate(步长)可以适当的增大</li></ul></li><li>反思:<ul><li>how does batch normalization help optimization?<ul><li>change the landscape of error surface.</li></ul></li></ul></li></ul>]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>笔记</tag>
</tags>
</entry>
<entry>
<title>机器学习2021-HW1</title>
<link href="/2024/09/29/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-HW1/"/>
<url>/2024/09/29/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A02021-HW1/</url>
<content type="html"><![CDATA[<h2 id="HomeWork1-COVID-19-Cases-Prediction-Regression"><a href="#HomeWork1-COVID-19-Cases-Prediction-Regression" class="headerlink" title="HomeWork1: COVID-19 Cases Prediction (Regression)"></a>HomeWork1: <strong>COVID-19 Cases Prediction (Regression)</strong></h2><p>kaggle:<a href="https://www.kaggle.com/competitions/ml2021spring-hw1/submissions#">https://www.kaggle.com/competitions/ml2021spring-hw1/submissions#</a></p><p>初始code:<a href="https://colab.research.google.com/github/ga642381/ML2021-Spring/blob/main/HW01/HW01.ipynb">https://colab.research.google.com/github/ga642381/ML2021-Spring/blob/main/HW01/HW01.ipynb</a></p><p>参考:</p><p><a href="https://github.com/1am9trash/Hung_Yi_Lee_ML_2021/blob/main/hw/hw1/hw1_code.ipynb">https://github.com/1am9trash/Hung_Yi_Lee_ML_2021/blob/main/hw/hw1/hw1_code.ipynb</a></p><p><a href="https://github.com/pai4451/ML2021">https://github.com/pai4451/ML2021</a></p><h3 id="问题与思路(9-27):"><a href="#问题与思路(9-27):" class="headerlink" title="问题与思路(9.27):"></a>问题与思路(9.27):</h3><ul><li>首先是python语法不熟悉,看得比较慢<ul><li>一点点看下来,一点点gpt其实还好,慢慢地就学进去了</li><li>整理一下,多多复习</li></ul></li><li>关键函数看不懂,涉及到复杂的python语法以及原理<ul><li>一点点梳理,<strong>先理解原理,再去尝试看懂代码</strong>,可以手打一下或者抄一下</li><li>多看几遍,慢慢来</li></ul></li><li>整个的流程还是不清晰的,有点困于细节<ul><li>大的流程就是1.写带未知参的function。2.定义loss。3.优化</li><li>先把原始作业版本的流程搞清楚,再去看优化</li><li><strong>先搞懂每段代码是做什么,把所有的代码块串接起来,关注重点内容,再去看细节</strong></li></ul></li></ul><h3 id="过程梳理:"><a href="#过程梳理:" class="headerlink" title="过程梳理:"></a>过程梳理:</h3><ul><li>目标:<ul><li>用DNN解决一个Regression problem</li><li>了解DNN training tips</li><li>熟悉PyTorch</li></ul></li><li>准备:<ul><li>Download Data, Import some packages and utilities</li></ul></li><li>Preprocess:(包含train,dev,test)<ul><li>DataSet<ul><li>read csv file</li><li><strong><code>extract features</code></strong></li><li>split train into train and dev sets</li><li><strong><code>normalize features</code></strong></li></ul></li><li>DataLoader<ul><li>loads data from DataSet into <strong><code>batches</code></strong></li></ul></li></ul></li><li>Deep Neural Network:<ul><li>nn.Module designed for regression</li><li>consists of <strong><code>2 fully-connected</code></strong> layer with <strong><code>ReLU</code></strong> activation</li><li><strong><code>cal_loss</code></strong> for calculating loss</li></ul></li><li>Train/Dev/Test:<ul><li>Training<ul><li>设置参数</li><li>训练循环(epoch)<ul><li>训练模式</li><li>数据迭代(update)<ul><li>梯度清零</li><li>数据传输</li><li>前向传播</li><li>计算损失(cal_loss)</li><li>反向传播</li><li><strong><code>更新参数</code></strong></li><li>记录损失</li></ul></li><li><strong><code>验证模型(dev)</code></strong></li><li>更新最小损失</li><li>早停技术</li><li>增加epoch</li><li>记录验证损失</li><li>早停检查</li></ul></li><li>结束打印,返回最小损失和损失记录</li></ul></li><li>Validation<ul><li>评估模式</li><li>初始化损失为0</li><li>数据迭代<ul><li>数据传输</li><li><strong><code>禁用梯度计算</code></strong></li><li>前向传播</li><li>计算损失(cal_loss)</li><li>累积损失</li></ul></li><li>计算返回平均损失</li></ul></li><li>Testing<ul><li>评估模式</li><li>初始化预测列表</li><li>数据迭代<ul><li>数据传输</li><li><strong><code>禁用梯度计算</code></strong></li><li>前向传播</li><li>收集预测</li></ul></li><li>合并结果为张量</li><li>返回预测结果</li></ul></li></ul></li><li>Setup Hyper-parameters:<ul><li>设置**<code>config</code>**里的超参数</li></ul></li><li>实操调用<ul><li>Load data and model</li><li>Start training(train()): 传入:tr_set,dev_set,model,config,device</li><li>Testing(test()):传入:tt_set,model,device, 保存结果到一个csv文件中</li></ul></li></ul><h3 id="重点代码理解:"><a href="#重点代码理解:" class="headerlink" title="重点代码理解:"></a>重点代码理解:</h3><p><strong>1.extract features:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-comment"># 查看数据量</span><br><span class="hljs-built_in">print</span>(<span class="hljs-string">"Train:{:4d}"</span>.<span class="hljs-built_in">format</span>(<span class="hljs-built_in">len</span>(train_data)))<br><span class="hljs-built_in">print</span>(<span class="hljs-string">" Test:{:4d}"</span>.<span class="hljs-built_in">format</span>(<span class="hljs-built_in">len</span>(test_data)))<br><span class="hljs-comment"># 查看表信息</span><br><span class="hljs-built_in">print</span>(train_data.info())<br><span class="hljs-comment"># 观察数值型数据分布情况</span><br>train_data.iloc[:,<span class="hljs-number">41</span>:].describe()<br>test_data.iloc[:,<span class="hljs-number">41</span>:].describe()<br><span class="hljs-comment"># 计算features与target之间的相关性并extract对应的features以及它们的index</span><br>corr = train_data.iloc[:,<span class="hljs-number">41</span>:].corr().iloc[-<span class="hljs-number">1</span>]<br>features = corr[<span class="hljs-built_in">abs</span>(corr)><span class="hljs-number">0.4</span>]<br>features_col = features.index.to_list()[:-<span class="hljs-number">1</span>]<br>features_id = np.array([train_data.columns.to_list().index(i) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> features_col]) - <span class="hljs-number">1</span><br><span class="hljs-built_in">print</span>(features)<br><span class="hljs-built_in">print</span>(<span class="hljs-string">"\\nfeatures' id:"</span>, <span class="hljs-string">', '</span>.join(<span class="hljs-built_in">map</span>(<span class="hljs-built_in">str</span>, features_id)))<br></code></pre></td></tr></table></figure><p><strong>2.normalize features:减去均值,除以标准差,得到均值为0,标准差为1的数据集</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><code class="hljs python">self.data[:, <span class="hljs-number">40</span>:] = \\<br> (self.data[:, <span class="hljs-number">40</span>:] - self.data[:, <span class="hljs-number">40</span>:].mean(dim=<span class="hljs-number">0</span>, keepdim=<span class="hljs-literal">True</span>)) \\<br> / self.data[:, <span class="hljs-number">40</span>:].std(dim=<span class="hljs-number">0</span>, keepdim=<span class="hljs-literal">True</span>)<br></code></pre></td></tr></table></figure><p><strong>3.批量数据加载器</strong>:调用之前写好的COVID19Dataset,对训练数据进行shuffle并返回批量数据</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">prep_dataloader</span>(<span class="hljs-params">path, mode, batch_size, n_jobs=<span class="hljs-number">0</span>, target_only=<span class="hljs-literal">False</span></span>):<br> <span class="hljs-string">''' Generates a dataset, then is put into a dataloader. '''</span><br> dataset = COVID19Dataset(path, mode=mode, target_only=target_only) <span class="hljs-comment"># Construct dataset</span><br> dataloader = DataLoader(<br> dataset, batch_size,<br> shuffle=(mode == <span class="hljs-string">'train'</span>), drop_last=<span class="hljs-literal">False</span>,<br> num_workers=n_jobs, pin_memory=<span class="hljs-literal">True</span>) <span class="hljs-comment"># Construct dataloader</span><br> <span class="hljs-keyword">return</span> dataloader<br></code></pre></td></tr></table></figure><p><strong>4.DNN</strong>:NeuralNet,设置神经网络层数和激活函数,以及在cal_loss里添加正则化</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs python">self.net = nn.Sequential(<br> nn.Linear(input_dim, <span class="hljs-number">64</span>),<br> nn.ReLU(),<br> nn.Linear(<span class="hljs-number">64</span>, <span class="hljs-number">1</span>)<br> )<br></code></pre></td></tr></table></figure><ul><li>nn.Sequential是一个容器,按顺序组合多个神经网络层</li><li>nn.Linear(input_dim, 64)是一个全连接层,针对输入,输出64个特征</li><li>nn.ReLU(),使用激活函数ReLU,增加模型的非线性,增加模型的表达能力</li><li>nn.Linear(64, 1),针对64维的输入,输出最终的结果,一个标量</li></ul><p><strong>5.cal_loss以及正则化</strong>:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">def</span> <span class="hljs-title function_">cal_loss</span>(<span class="hljs-params">self, y, y_hat</span>):<br> <span class="hljs-string">""" Calculate loss """</span><br> loss = torch.sqrt(self.criterion(y, y_hat))<br> <span class="hljs-comment"># l2 = 0</span><br> <span class="hljs-comment"># for i in self.parameters():</span><br> <span class="hljs-comment"># l2 += torch.sum(torch.pow(i, 2))</span><br> <span class="hljs-comment"># return loss + 0.01 * l2, loss</span><br> l1 = <span class="hljs-number">0</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> self.parameters():<br> l1 += torch.<span class="hljs-built_in">sum</span>(<span class="hljs-built_in">abs</span>(i))<br> <span class="hljs-keyword">return</span> loss + <span class="hljs-number">0.0001</span> * l1, loss<br></code></pre></td></tr></table></figure><ul><li>这里采取了RMSE作为loss function</li><li>L1正则化就是计算参数绝对值的和,L2正则化就是计算参数平方的和</li><li>返回loss+正则化结果*超参数</li></ul><p><strong>6.设置超参数:</strong></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs python">config = {<br> <span class="hljs-string">'n_epochs'</span>: <span class="hljs-number">3000</span>, <span class="hljs-comment"># maximum number of epochs</span><br> <span class="hljs-string">'batch_size'</span>: <span class="hljs-number">270</span>, <span class="hljs-comment"># mini-batch size for dataloader</span><br> <span class="hljs-string">'optimizer'</span>: <span class="hljs-string">'SGD'</span>, <span class="hljs-comment"># optimization algorithm (optimizer in torch.optim)</span><br> <span class="hljs-string">'optim_hparas'</span>: { <span class="hljs-comment"># hyper-parameters for the optimizer (depends on which optimizer you are using)</span><br> <span class="hljs-string">'lr'</span>: <span class="hljs-number">0.001</span>, <span class="hljs-comment"># learning rate of SGD</span><br> <span class="hljs-string">'momentum'</span>: <span class="hljs-number">0.9</span> <span class="hljs-comment"># momentum for SGD</span><br> },<br> <span class="hljs-string">'early_stop'</span>: <span class="hljs-number">200</span>, <span class="hljs-comment"># early stopping epochs (the number epochs since your model's last improvement)</span><br> <span class="hljs-string">'save_path'</span>: <span class="hljs-string">'models/model.pth'</span> <span class="hljs-comment"># your model will be saved here</span><br>}<br></code></pre></td></tr></table></figure><ul><li>‘optimizer’: ‘SGD’是随机梯度下降优化算法</li><li>momentum是考虑之前所有g的加权和,在梯度方向上积累历史信息,加快在平坦区域的收敛速度,减缓在梯度方向变化剧烈的收敛速度2</li><li>early_stop:表示当dev_mse连续很久没有更新,就提前停止退出</li></ul><h3 id="分析和改善:"><a href="#分析和改善:" class="headerlink" title="分析和改善:"></a>分析和改善:</h3><h3 id="记录:"><a href="#记录:" class="headerlink" title="记录:"></a>记录:</h3><table><thead><tr><th>idx</th><th>version</th><th>valid</th><th>public</th><th>private</th><th>desc</th></tr></thead><tbody><tr><td>1</td><td>什么都没增加,最原始的代码</td><td>0.7590</td><td><strong>1.35281</strong></td><td>1.43395</td><td>运行一遍,跑通所有代码</td></tr><tr><td>2</td><td>最完整的版本</td><td>0.9296</td><td><strong>0.87971</strong></td><td>0.89165</td><td>运行了一下完整的参考代码</td></tr><tr><td>3</td><td>增加强相关度的features筛选,增加了正则化,损失函数用RMSE计算</td><td>0.9138</td><td><strong>1.02623</strong></td><td>1.04953</td><td>在1的基础上只修改了features选址部分,增加了loss计算时的l1正则化,损失函数从MSE到RMSE</td></tr><tr><td>4</td><td>增加强相关度的features筛选,增加了正则化,损失函数用MSE计算</td><td>0.8360</td><td><strong>1.00645</strong></td><td>1.04458</td><td>在3的基础上把RMSE改为MSE</td></tr><tr><td>5</td><td>增加强相关度的features筛选,增加了正则化(参数修改为0.001),损失函数用MSE计算</td><td>1.0079</td><td><strong>0.96859</strong></td><td>1.00816</td><td>在4的基础上修改了L1正则化的强度参数,从0.0001到0.001</td></tr><tr><td>6</td><td>增加了epoch的上限</td><td>0.9229</td><td><strong>0.95927</strong></td><td>1.01704</td><td>在5的基础上增大了epoch上限为20000</td></tr><tr><td>7</td><td>增加了layer层数</td><td>0.9538</td><td><strong>1.09354</strong></td><td>1.17069</td><td>在6的基础上增加了一层全连接层。有点过拟合了。</td></tr><tr><td>8</td><td>ReLU→Sigmoid</td><td>0.9914</td><td><strong>2.03473</strong></td><td>2.05528</td><td>在6的基础上修改了激活函数——过拟合很严重</td></tr><tr><td>9</td><td>重新归一化和划分数据集</td><td>0.9354</td><td><strong>1.01068</strong></td><td>1.06830</td><td>在6的基础上进行了归一化和划分数据集的修改</td></tr></tbody></table><p>TODO:</p><ul><li>歸一化 ✔<ul><li>原本範例code中是不同的dataset分別使用自己的mean跟std做歸一,這是不合理的,應該使用全部資料的mean跟data做歸一,才不會有太大的偏差</li></ul></li><li>Train跟Valid dataset切分✔<ul><li>改為隨機切分,保證資料分布相同</li><li>由於資料集太小,建議多切幾次避免將異常值劃分到valid(k-fold應該是個比較好的做法)</li></ul></li><li>修改了归一化和切分,并没有好的效果</li><li>DNN architecture (layers? dimension? activation function?)✔<ul><li><strong>尝试增加了一层layer,发现dev上的loss大幅增加</strong></li><li><strong>将ReLU改为Sigmoid发现overfitting很严重</strong></li></ul></li><li>Training (mini-batch? optimizer? learning rate?)✔<ul><li>降低了learning rate,有比较好的效果,也方便观察</li></ul></li><li>L1 regularization✔</li><li>There are some mistakes in the sample code, can you find them?</li></ul><h3 id="Hight-light(Training-tips)"><a href="#Hight-light(Training-tips)" class="headerlink" title="Hight light(Training tips):"></a>Hight light(Training tips):</h3><p><strong>1、在训练集上效果变差,在测试集上效果可能还是会变好</strong></p><ul><li><p>对比版本1和版本3发现了</p><p>一个有意思的现象</p><p>:</p><ul><li>版本1在训练集和验证集上效果都比较好,但是在测试集上效果差</li><li>而增加了强相关度的features筛选,增加了正则化的版本3却在训练集和验证集上效果都相对比较差,但是在测试集上效果相对更好</li></ul></li><li><p>原因:</p><ul><li><p>过拟合与泛化能力</p><p>:</p><ul><li>版本1: 由于其在训练集和验证集上表现较好,可能存在过拟合。模型过于复杂或参数过多,导致它很好地记住了训练数据,但在测试集上泛化能力较差。</li><li>版本3: 增加正则化后,模型的复杂度降低,更不容易过拟合。这可能导致训练和验证集的表现下降,但在测试集上提高了<strong>泛化能力</strong>,表现更好。</li></ul></li><li><p>强相关度特征筛选</p><p>:</p><ul><li>增加强相关特征可以帮助模型<strong>捕捉到数据的主要模式</strong>。这种特征选择可能提高了模型在未见数据(测试集)上的表现,尽管它在训练集上的拟合不如基础版本。</li></ul></li><li><p>正则化的作用</p><p>:</p><ul><li>正则化可以<strong>限制模型的复杂度,减少对训练数据噪声的敏感性</strong>。这样,即使在训练集上的损失相对较高,模型在面对新的数据时(如测试集)可能表现得更好。</li></ul></li><li><p>损失函数的变化</p><p>:</p><ul><li>从均方误差(MSE)改为均方根误差(RMSE)并不会改变模型的拟合过程,但 <strong>RMSE 在一定程度上会更加关注较大的误差</strong>。虽然这可能导致模型在训练和验证集上的表现不如基础版本,但有助于在测试集上提高表现,尤其是当测试集具有不同的分布时</li></ul></li></ul></li><li><p><strong>总结</strong>:优化手段都有点降低模型的复杂度,防止过拟合,增强的泛化,所以会有在训练集和验证集上效果一般,但是在测试集上效果很好的现象,这是很正常的。</p></li></ul><p><strong>2、RMSE→MSE,在dev上测试提前结束了</strong></p><ul><li><p>在版本3的基础上想着loss在验证集上偏大可能有也因为loss的计算方法不一样,于是把损失函数从RMSE变为MSE,但是发生了一个有意思的现象</p><ul><li>在dev上运行时,loss还很大,训练就停止了,触发了早停机制</li></ul></li><li><p>原因:</p><ul><li><p>优化算法的敏感性</p><p>:</p><ul><li>MSE <strong>对较大误差更敏感</strong>,导致损失更新不如 RMSE 稳定,从而更容易达到早停的条件。</li></ul></li><li><p>正则化影响</p><p>:</p><ul><li>如果你在 MSE 损失中加入了正则化项,模型可能会更快地达到损失的阈值,从而提前结束训练。</li></ul></li><li><p>数据集问题</p><p>:</p><ul><li>数据集中可能存在噪声或不一致性,导致模型在训练时<strong>难以收敛</strong>,尤其是在使用 MSE 时。</li></ul></li></ul></li><li><p>总结:</p><ul><li>设置的早停条件基于<strong>验证集损失在一定轮次内未改善</strong>,MSE 的<strong>波动</strong>可能导致模型在训练过程中的某个时刻没有明显改善,进而提前结束训练。</li></ul></li><li><p>解决:</p><ul><li>降低学习率:从0.001到0.0001,可以帮助平滑更新过程,减少损失的波动,最终训练出了不错的数据。</li></ul></li></ul><p><strong>3、修改正则化L1的超参数,模型性能真的有提高</strong></p><ul><li>发现版本4在dev上loss比较小,而在public的loss变大了不少。<strong>猜测</strong>模型<strong>有一点点过拟合的倾向</strong>,于是增大了L1的超参数,从0.0001到0.001,发现loss在dev上增加了一点,但是在public和test上均有下降</li><li>原因:<ul><li>该超参数为<strong>正则化强度</strong></li><li><strong>较小的值</strong>意味着正则化对损失的影响较小,可能导致过拟合,尤其是在训练数据较小或噪声较多的情况下。</li><li><strong>较大的值</strong>: 增加该值将增强正则化的效果,使模型更简单、更平滑。这可能改善模型的泛化能力,但也可能导致欠拟合,因为模型可能无法捕捉到数据中的重要特征。</li><li>补充:如何调整这个正则化强度<ul><li>可以通过<strong>交叉验证</strong>等方法尝试不同的正则化强度,观察对训练、验证和测试集性能的影响,找到最适合你模型的超参数。</li><li><strong>使用网格搜索或随机搜索</strong>: 帮助系统地寻找最佳的正则化强度。</li></ul></li></ul></li></ul><p><strong>4、增加layer训练时才发现之前的几次训练因为epoch上限的原因都及时停止了</strong></p><ul><li>分析:<ul><li>把epoch上限从3000提升到了20000,之前的模型效果在public上有变好,在private上略变差一点</li><li>增加了layer后,public的结果明显比dev上损失要高,猜测可能存在一些过拟合的风险</li></ul></li></ul><h3 id="总结:"><a href="#总结:" class="headerlink" title="总结:"></a>总结:</h3><ul><li>通过这次作业,对regression模型训练的<strong>实际操作流程</strong>有了更加深刻的认识</li><li>通过多次的反复调整模型,习得了一些training tip,如何判断是否是overfitting,进行optimize<ul><li>强相关性features的选取</li><li>正则化防止模型过于复杂</li><li>损失函数MSE和RMSE</li><li>learning rate的调整可以让模型走得更加平滑,减少损失波动(optimization)</li><li>所有数据统计归一化和train,dev数据集随机切分(效果不明显)、</li><li>修改DNN(layer,dimension,activation function)</li></ul></li><li>待进步:<ul><li><strong>整个调优的过程还是有点混乱,想到什么做什么,逻辑可以更加清晰,逐步地进行一个优化是一个比较好的过程</strong></li><li><strong>应该把train_loss也进行输出,比较train和dev来初步判断是否是overfitting,而不是通过dev和public,private进行比较</strong></li></ul></li></ul>]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>笔记</tag>
</tags>
</entry>
<entry>
<title>机器学习-基本概念</title>
<link href="/2024/09/24/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/"/>
<url>/2024/09/24/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0%E5%85%A5%E9%97%A8/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0-%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5/</url>
<content type="html"><![CDATA[<h1 id="机器学习基本概念总结"><a href="#机器学习基本概念总结" class="headerlink" title="机器学习基本概念总结"></a>机器学习基本概念总结</h1><p><img src="/img/ml1.jpg" alt="思维导图"></p>]]></content>
<categories>
<category>机器学习</category>
</categories>
<tags>
<tag>笔记</tag>
</tags>
</entry>
<entry>
<title>9.21-华为全联接大会</title>
<link href="/2024/09/24/%E7%94%9F%E6%B4%BB%E4%B8%8E%E6%8A%80%E6%9C%AF/9-21-%E5%8D%8E%E4%B8%BA%E5%85%A8%E8%81%94%E6%8E%A5%E5%A4%A7%E4%BC%9A/"/>
<url>/2024/09/24/%E7%94%9F%E6%B4%BB%E4%B8%8E%E6%8A%80%E6%9C%AF/9-21-%E5%8D%8E%E4%B8%BA%E5%85%A8%E8%81%94%E6%8E%A5%E5%A4%A7%E4%BC%9A/</url>
<content type="html"><![CDATA[<h1 id="9-21—华为全联接大会"><a href="#9-21—华为全联接大会" class="headerlink" title="9.21—华为全联接大会"></a>9.21—华为全联接大会</h1><h3 id="时间线:"><a href="#时间线:" class="headerlink" title="时间线:"></a>时间线:</h3><ul><li>上午:听华为产品的发布会:<ul><li><strong>鸿蒙OS,鸿蒙生态</strong></li></ul></li><li>中午:小逛了一下各个集市展览:<ul><li>机器狗(云深处)—用于电站、工厂、管廊巡检,应急救援、消防侦查</li><li>病例生成、诊疗分析大模型,药物分拣机器人</li></ul></li><li>下午:参加了三场学术会议:<ul><li>基于CANN的计算机视觉和多模态大模型应用<ul><li>视频增强修复<ul><li>背景:老视频的像素提升</li><li>应用:AI视频修复平台,智能超分系统</li></ul></li><li>端侧端云的机器人技术研究</li></ul></li><li>基于现实世界的AI三维场景重建:南京大学某个实验室<ul><li>图形学:信息到图像,视觉:图像到信息</li><li>学术:重建,应用:数字孪生,智能化建模重建,三维数字人生成</li><li>NeRF系列</li></ul></li><li>面向资源受限场景的基础模型关键技术及应用<ul><li>背景:关注大模型的推理能力和成本两个问题</li><li>端侧是AI在终端场景落地的核心技术</li><li>研究思路:高效化、轻量化模型(有点反着走的感觉)</li></ul></li></ul></li></ul><h3 id="体会:"><a href="#体会:" class="headerlink" title="体会:"></a>体会:</h3><ul><li>时间关系,那些集市展览看得比较少,其实可以多多去和那里的技术人员交流,哪怕是提很简单的问题——>要提升自己的表达能力,交流能力。</li><li>听了学术会议的最大感受是自己知道的太少,没能从中学习到一些学术研究的思路,快速了解他们做的内容。可以听懂,但听不明白。——>怎么抓住重点呢?怎么从中发现一些启发性的思路呢?我想我需要对学术研究先有一个过程的了解。</li><li>这次走的太早了,有点遗憾。——>听会议后,其实是可以旁观一下他们的会后交流的,多听听,多看看。</li></ul><h3 id="总结:"><a href="#总结:" class="headerlink" title="总结:"></a>总结:</h3><ul><li>很长见识的一场活动,开拓了眼界,氛围很棒</li><li>学到了不少,认识到还有很多值得进步发展的地方</li><li>以后这类活动要积极参加,很值得!</li></ul>]]></content>
<categories>
<category>人文</category>
</categories>
<tags>
<tag>活动</tag>
</tags>
</entry>
<entry>
<title>MBTI性格测试小程序项目</title>
<link href="/2024/09/21/project/MBTI%E6%80%A7%E6%A0%BC%E6%B5%8B%E8%AF%95%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%A1%B9%E7%9B%AE/"/>
<url>/2024/09/21/project/MBTI%E6%80%A7%E6%A0%BC%E6%B5%8B%E8%AF%95%E5%B0%8F%E7%A8%8B%E5%BA%8F%E9%A1%B9%E7%9B%AE/</url>
<content type="html"><![CDATA[<h1 id="MBTI-性格测试小程序"><a href="#MBTI-性格测试小程序" class="headerlink" title="MBTI 性格测试小程序"></a><strong>MBTI 性格测试小程序</strong></h1><p>Github地址:<a href="https://github.com/chuanshanh/jhxdada">https://github.com/chuanshanh/jhxdada</a></p><h2 id="零、放在前面"><a href="#零、放在前面" class="headerlink" title="零、放在前面"></a>零、放在前面</h2><h5 id="一些介绍:"><a href="#一些介绍:" class="headerlink" title="一些介绍:"></a>一些介绍:</h5><ul><li>是鱼皮的一个项目的第一阶段,做一个性格测试的小程序,为后面的AI答题应用平台做准备</li><li>由于算法设计比较简单,可以直接放在前端,所以没有后台</li><li>通过三个核心页面的开发学习了前端React的基于Taro的基本开发流程:<strong>界面—-样式—-逻辑</strong></li><li>还有小程序开发过程中常见问题的解决:主要是小程序开发者工具的重载</li><li>体验了CodeGeex这一AI开发工具:偶尔的代码自动补全是管点用的,但是问答能力还是不如GPT,对提示词要求还蛮高的。</li></ul><h2 id="一、MBTI-性格测试应用介绍"><a href="#一、MBTI-性格测试应用介绍" class="headerlink" title="一、MBTI 性格测试应用介绍"></a><strong>一、MBTI 性格测试应用介绍</strong></h2><p>参考项目:<a href="https://www.16personalities.com/ch">https://www.16personalities.com/ch</a></p><p>大致可以分为主页、答题页面、结果页面三个主要的页面</p><h2 id="二、MBTI-实现方案介绍"><a href="#二、MBTI-实现方案介绍" class="headerlink" title="二、MBTI 实现方案介绍"></a><strong>二、MBTI 实现方案介绍</strong></h2><p>核心:题目、用户答案、评分规则</p><h3 id="1、题目结构:"><a href="#1、题目结构:" class="headerlink" title="1、题目结构:"></a>1、题目结构:</h3><p>采用JSON格式,相比于拿选项作为key,每个选项单独存储在options里,方便进行扩展,并且更加灵活,可以进行排序。</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">[</span><br> <span class="hljs-punctuation">{</span><br> <span class="hljs-attr">"title"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"你通常更喜欢"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"options"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><br> <span class="hljs-punctuation">{</span><br> <span class="hljs-attr">"result"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"I"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"value"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"独自工作"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"key"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"A"</span><br> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span><br> <span class="hljs-punctuation">{</span><br> <span class="hljs-attr">"result"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"E"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"value"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"与他人合作"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"key"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"B"</span><br> <span class="hljs-punctuation">}</span><br> <span class="hljs-punctuation">]</span><br> <span class="hljs-punctuation">}</span><br><span class="hljs-punctuation">]</span><br></code></pre></td></tr></table></figure><h3 id="2、用户答案结构"><a href="#2、用户答案结构" class="headerlink" title="2、用户答案结构"></a>2、用户答案结构</h3><p>用一个数组进行存储,而不是放在刚才的题目结构里,不需要传递完整的题目结构,大大节约了空间</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">[</span><span class="hljs-string">"A"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"A"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"A"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"B"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"A"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"A"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"A"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"B"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"B"</span><span class="hljs-punctuation">,</span><span class="hljs-string">"A"</span><span class="hljs-punctuation">]</span><br></code></pre></td></tr></table></figure><h3 id="3、评分规则"><a href="#3、评分规则" class="headerlink" title="3、评分规则"></a>3、评分规则</h3><p>参考:<a href="https://zh.wikipedia.org/wiki/%E9%82%81%E7%88%BE%E6%96%AF-%E5%B8%83%E9%87%8C%E6%A0%BC%E6%96%AF%E6%80%A7%E6%A0%BC%E5%88%86%E9%A1%9E%E6%B3%95">https://zh.wikipedia.org/wiki/邁爾斯-布里格斯性格分類法</a></p><p>MBTI将心理差异分类为4个对立的组合(或称“<a href="https://zh.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%B3%95">二分法</a>”),一个人在每个组合中各拥有1个偏好[<a href="https://zh.wikipedia.org/wiki/%E9%82%81%E7%88%BE%E6%96%AF-%E5%B8%83%E9%87%8C%E6%A0%BC%E6%96%AF%E6%80%A7%E6%A0%BC%E5%88%86%E9%A1%9E%E6%B3%95#cite_note-:1-8">7]</a>:</p><ul><li>内向与外向(I/E)</li><li>实感与直觉(S/N)</li><li>思考与情感(T/F)</li><li>判断与感知(J/P)</li></ul><p>那么,每道题目会对应一个组合,选项来判断是其中的哪一个,然后根据所有结果的数量,对16种结果进行计数(含有这一字母的加一分),得分最高的就是结果。</p><p>例子:</p><p>给每个选择的答案对应设置一个 <strong>属性</strong>。简单举例,比如</p><ul><li>第一题 A 对应 I,B 对应 E</li><li>第二题 A 对应 E,B 对应 I</li><li>第三题 A 对应 S, B 对应 N</li><li>第四题 A 对应 T, B 对应 F</li><li>第五题 A 对应 P, B 对应 J</li></ul><p>那么如果用户选择了 [A,B,A,A,A],可以算出用户有两个 I,一个 S ,一个 T 一个 P,很明显他是 ISTP 人格。</p><p>评分结果JSON结构:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-punctuation">[</span><br> <span class="hljs-punctuation">{</span><br> <span class="hljs-attr">"resultProp"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><br> <span class="hljs-string">"I"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"S"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"T"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"J"</span><br> <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"resultDesc"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"忠诚可靠,被公认为务实,注重细节。"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"resultPicture"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"icon_url_istj"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"resultName"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ISTJ(物流师)"</span><br> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">,</span><br> <span class="hljs-punctuation">{</span><br> <span class="hljs-attr">"resultProp"</span><span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><br> <span class="hljs-string">"I"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"S"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"F"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-string">"J"</span><br> <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"resultDesc"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"善良贴心,以同情心和责任为特点。"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"resultPicture"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"icon_url_isfj"</span><span class="hljs-punctuation">,</span><br> <span class="hljs-attr">"resultName"</span><span class="hljs-punctuation">:</span> <span class="hljs-string">"ISFJ(守护者)"</span><br> <span class="hljs-punctuation">}</span><br><span class="hljs-punctuation">]</span><br></code></pre></td></tr></table></figure><h2 id="三、MBTI-小程序-Demo-数据"><a href="#三、MBTI-小程序-Demo-数据" class="headerlink" title="三、MBTI 小程序 Demo 数据"></a><strong>三、MBTI 小程序 Demo 数据</strong></h2><h2 id="四、Taro-跨端小程序开发入门"><a href="#四、Taro-跨端小程序开发入门" class="headerlink" title="四、Taro 跨端小程序开发入门"></a><strong>四、Taro 跨端小程序开发入门</strong></h2><p><strong>环境准备:node:18.16.0 npm:9.5.1(原先:node:14.21.3, npm:8.1.2)</strong></p><p>nodejs:</p><p>nvm list查看已安装版本</p><p>nvm install 16.13.0安装某个版本</p><p>nvm use 18.16.0使用某个版本</p><p>npm:</p><p>npm install -g <a href="mailto:npm@9.5.1">npm@9.5.1</a></p><p><strong>Taro下载:</strong></p><p>Taro默认下载的是最新版本,最好还是指定版本下载</p><p>解决:npm install -g @tarojs/<a href="mailto:cli@3.6.28">cli@3.6.28</a></p><p>Tato下载好后无法查看版本,报错无法识别taro</p><p>解决:在环境变量的Path中增加D:\nodejs\node_global</p><p><strong>初始化Taro框架:</strong></p><p>前端采用React,组件库采用Taro UI</p><p>终端:npm install 配置依赖,运行<strong>npm run build:weapp – –watch</strong></p><p><strong>微信开发者工具打开项目:</strong>主要关注预览效果和编译报错</p><p><strong>配置项目开发规范:</strong></p><p>eslint:校验JS代码,给语法提示;</p><p>typescript:校验语法,给语法提示</p><p>prettier:代码美化工具,快速格式化代码</p><p>当eslint和prettier发生冲突时,在eslint的配置文件里忽略掉它的对应的检查</p><p><strong>测试组件Taro UI引入,来上手开发页面:</strong></p><p>在app.ts即入口文件中全局引入:</p><p>import ‘taro-ui/dist/style/index.scss’ // 引入组件样式 - 方式一</p><p>然后尝试引入一个 taro-ui 组件。</p><p><strong>前端经典开发顺序:页面—样式—逻辑(比如JS交互)</strong></p><p><strong>开发示例页面:</strong></p><p>1)找到应用全局配置文件 app.config.ts,新增页面路由(最上面的是打开默认的页面)</p><p>2)复制已有页面文件,创建新页面</p><p>3)根据自己的需要,复制组件,拼出完整页面</p><p>4)根据自己的需求,定制开发</p><p>5)演示页面之间的跳转:<strong>页面跳转(查</strong><a href="https://taro-docs.jd.com/docs/router#%E8%B7%AF%E7%94%B1%E8%B7%B3%E8%BD%AC**%EF%BC%89">https://taro-docs.jd.com/docs/router#路由跳转**)</a>**</p><h2 id="五、MBTI-跨端小程序开发实战"><a href="#五、MBTI-跨端小程序开发实战" class="headerlink" title="五、MBTI 跨端小程序开发实战"></a><strong>五、MBTI 跨端小程序开发实战</strong></h2><p><strong>1.全局规范和配置:</strong></p><p>遵循函数式组件的写法:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs json">export default () => <span class="hljs-punctuation">{</span><br> return (<br> <View className=<span class="hljs-string">"index"</span>><br> <Text>Hello world!</Text><br> </View><br> );<br><span class="hljs-punctuation">}</span>;<br></code></pre></td></tr></table></figure><p>修改应用标题:</p><p>修改app.config.ts全局配置文件里的title</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs json">export default defineAppConfig(<span class="hljs-punctuation">{</span><br> pages<span class="hljs-punctuation">:</span> <span class="hljs-punctuation">[</span><br> 'pages/index/index'<br> <span class="hljs-punctuation">]</span><span class="hljs-punctuation">,</span><br> window<span class="hljs-punctuation">:</span> <span class="hljs-punctuation">{</span><br> backgroundTextStyle<span class="hljs-punctuation">:</span> 'light'<span class="hljs-punctuation">,</span><br> navigationBarBackgroundColor<span class="hljs-punctuation">:</span> '#fff'<span class="hljs-punctuation">,</span><br> navigationBarTitleText<span class="hljs-punctuation">:</span> 'MBTI 性格测试'<span class="hljs-punctuation">,</span><br> navigationBarTextStyle<span class="hljs-punctuation">:</span> 'black'<br> <span class="hljs-punctuation">}</span><br><span class="hljs-punctuation">}</span>)<br></code></pre></td></tr></table></figure><p><strong>2.主页:先做内容,再把内容抽象成对象来增加样式</strong></p><p>在app.scss里全局修改按钮主题色:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs json">.at-button--primary<span class="hljs-punctuation">{</span><br> background<span class="hljs-punctuation">:</span> #<span class="hljs-number">806497</span>;<br> border-color<span class="hljs-punctuation">:</span> #<span class="hljs-number">806497</span>;<br><span class="hljs-punctuation">}</span><br></code></pre></td></tr></table></figure><p>主页核心页面代码:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs json"><span class="hljs-comment">/**</span><br><span class="hljs-comment"> * 主页</span><br><span class="hljs-comment"> */</span><br>export default () => <span class="hljs-punctuation">{</span><br> return (<br> <View className=<span class="hljs-string">"indexPage"</span>><br> <View className=<span class="hljs-string">"at-article__h1 title"</span>>MBTI性格测试</View><br> <View className=<span class="hljs-string">"at-article__h2 subTitle"</span>><br> 只需<span class="hljs-number">2</span>分钟,就能非常准确地描述出你是谁,以及你的性格特点<br> </View><br> <AtButton type=<span class="hljs-string">"primary"</span> circle className=<span class="hljs-string">"enterBtn"</span>><br> 开始测试<br> </AtButton><br> <Image<br> className=<span class="hljs-string">"HeaderBg"</span><br> style=<span class="hljs-string">"width: 400px;height: 400px;"</span><br> src=<span class="hljs-punctuation">{</span>HeaderBg<span class="hljs-punctuation">}</span><br> /><br> <GlobalFooter /><br> </View><br> );<br><span class="hljs-punctuation">}</span>;<br></code></pre></td></tr></table></figure><p>主页核心样式代码:</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs json">.indexPage<span class="hljs-punctuation">{</span><br> background<span class="hljs-punctuation">:</span> #A2C7D7;<br> height<span class="hljs-punctuation">:</span> <span class="hljs-number">93</span>vh;<br> .title<span class="hljs-punctuation">{</span><br> color<span class="hljs-punctuation">:</span>white;<br> padding-top<span class="hljs-punctuation">:</span> <span class="hljs-number">48</span>px;<br> text-align<span class="hljs-punctuation">:</span> center;<br> <span class="hljs-punctuation">}</span><br> .subTitle<span class="hljs-punctuation">{</span><br> color<span class="hljs-punctuation">:</span>white;<br> margin-bottom<span class="hljs-punctuation">:</span> <span class="hljs-number">48</span>px;<br> <span class="hljs-punctuation">}</span><br><br> .enterBtn<span class="hljs-punctuation">{</span><br> width<span class="hljs-punctuation">:</span> <span class="hljs-number">60</span>vw;<br> <span class="hljs-punctuation">}</span><br><br><span class="hljs-punctuation">}</span><br></code></pre></td></tr></table></figure><p><strong>3.答题页面</strong></p><p>开发步骤:</p><p>1)先写<strong>页面</strong>:</p><p>包括题目(序号+题目内容),选项(key+value),切题按钮(下一题,查看结果,上一题)</p><p>2)再调整<strong>样式</strong>:</p><p>字体大小,按钮样式位置</p><p>3)最后再写<strong>逻辑</strong>(上一题、下一题)</p><p>先控制是否展示按钮</p><p>控制切换,切换不同的题目和答案(useEffect),设定必须选了才能到下一题</p><p>记录答案(JSON输出验证)</p><p><strong>4、查看结果页面</strong></p><p>1)先写页面:包含两个文字(resultName和resultDesc),一个按钮</p><p>2)实现三个页面之间的跳转(通过给按钮增加时间,另外,从结果跳转到主页要使用reLauch,防止页面的无限增加)</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs json"><AtButton<br> type=<span class="hljs-string">"primary"</span><br> circle<br> className=<span class="hljs-string">"enterBtn"</span><br> onClick=<span class="hljs-punctuation">{</span>() => <span class="hljs-punctuation">{</span><br> Taro.navigateTo(<span class="hljs-punctuation">{</span><br> url<span class="hljs-punctuation">:</span> '/pages/doQuestion/index'<span class="hljs-punctuation">,</span><br> <span class="hljs-punctuation">}</span>);<br> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><br> ><br> 开始测试<br> </AtButton><br><AtButton<br> type=<span class="hljs-string">"primary"</span><br> circle<br> className=<span class="hljs-string">"enterBtn"</span><br> onClick=<span class="hljs-punctuation">{</span>() => <span class="hljs-punctuation">{</span><br> Taro.reLaunch(<span class="hljs-punctuation">{</span><br> url<span class="hljs-punctuation">:</span> '/pages/index/index'<span class="hljs-punctuation">,</span><br> <span class="hljs-punctuation">}</span>);<br> <span class="hljs-punctuation">}</span><span class="hljs-punctuation">}</span><br> > <br> 返回主页<br> </AtButton><br></code></pre></td></tr></table></figure><p><strong>5、评分模块实现</strong></p><p>可以根据AI工具CodeGeex尝试进行生成</p><p>有两种算法实现:</p><p>1.先把answerList转化为对应的人格列表optionCount(比如I,S,T,J)遍历所有question_result,然后遍历optionCount,有里面的字母就加1,看最终哪个得分最高</p><p>2.提前统计optionCount里各个字母的数量,然后遍历所有question_result,直接获得得分,将最高分的结果返回</p><p><strong>6、页面间数据传递</strong></p><p>方法 1:url params</p><p><a href="https://taro-docs.jd.com/docs/apis/route/navigateTo">https://taro-docs.jd.com/docs/apis/route/navigateTo</a></p><p>比如:result?answerList=[A,B,C]1826449162109644801_0.9446173137808922</p><p>方法 2:全局状态</p><p><a href="https://taro-docs.jd.com/docs/context#contextprovider">https://taro-docs.jd.com/docs/context#contextprovider</a></p><p>方法 3:本地数据存储(推荐,较为简单)1826449162109644801_0.10902648018201178</p><p><a href="https://taro-docs.jd.com/docs/apis/storage/setStorageSync">https://taro-docs.jd.com/docs/apis/storage/setStorageSync</a></p><p>采用方法3,在做完题目点击按钮,跳转前对answerList进行本地数据存储,然后在查看结果页面使用数据,注意特殊判断结果是否为空,是的话使用Toast进行保存</p><p>PS:遇事不决 3 件套:清理工具缓存、重启项目、重启开发者工具。</p><h2 id="六、小程序开发常用解决方案"><a href="#六、小程序开发常用解决方案" class="headerlink" title="六、小程序开发常用解决方案"></a><strong>六、小程序开发常用解决方案</strong></h2><h3 id="1、小程序调试发布"><a href="#1、小程序调试发布" class="headerlink" title="1、小程序调试发布"></a><strong>1、小程序调试发布</strong></h3><p>需要正式的 appId(到微信小程序官方申请),开发前多去看看微信小程序官方文档的审核要求。</p><p>1)执行 build 命令打包代码</p><p>删除 dist 目录,清理开发者工具缓存,执行 <code>build:weapp</code>,再次运行,验证效果。</p><p>小程序发包有限制,一定要用 build 去构建,体积更小。</p><p>2)有了正式的 AppId(测试号也可以)后,可以真机调试。</p><p>3)在微信小程序开发工具上传代码</p><h3 id="2、网络请求"><a href="#2、网络请求" class="headerlink" title="2、网络请求"></a><strong>2、网络请求</strong></h3><p><strong>请求库</strong></p><p>主流的网络请求库是 <strong>Axios</strong>,但是小程序环境中无法直接使用 Axios。</p><p>推荐使用适配器库:<a href="https://github.com/bigmeow/taro-platform/tree/master/packages/axios-taro-adapter">https://github.com/bigmeow/taro-platform/tree/master/packages/axios-taro-adapter</a></p><p><strong>请求代码生成</strong></p><p>传统开发方式:每一个请求写一个发送请求的代码</p><p>更高效的开发方式:根据后端 OpenAPI 规范的接口文档(比如 <strong>Swagger</strong>)自动生成请求,推荐:<a href="https://www.npmjs.com/package/@umijs/openapi">https://www.npmjs.com/package/@umijs/openapi</a></p><p><strong>全局请求处理器</strong></p><p>可以自己定义请求的全局参数、增加全局请求处理器、响应处理器等,参考 Axios 文档:<a href="https://axios-http.com/docs/instance">https://axios-http.com/docs/instance</a> 。</p><h3 id="3、状态管理"><a href="#3、状态管理" class="headerlink" title="3、状态管理"></a><strong>3、状态管理</strong></h3><p>多个页面(整个应用)共享变量,当变量发生变化时可以触发界面更新等。</p><p><strong>创建一个全局 JS 变量、或者利用小程序存储能力(Storage)</strong>共享变量即可。</p><p>使用 Redux 的工具库实现全局状态管理:<a href="https://react-redux.js.org/tutorials/quick-start">https://react-redux.js.org/tutorials/quick-start</a></p><h3 id="4、用户登录"><a href="#4、用户登录" class="headerlink" title="4、用户登录"></a><strong>4、用户登录</strong></h3><p><strong>小程序登录原理</strong></p><p>理论上用户打开小程序就可以自动登录,不需要自己点按钮,只不过获取不到昵称和头像罢了。</p><p>所有 wx 小程序的原生函数在 Taro 几乎都有对应的接口,比如 Taro.login == wx.login。</p><p><a href="https://docs.taro.zone/docs/apis/open-api/login/">https://docs.taro.zone/docs/apis/open-api/login/</a></p><p><strong>怎么存储 session 和携带 cookie 信息?</strong></p><p>相比于 web 开发,小程序除了可能要维护已登录用户信息外,还要自己额外维护 cookie。</p><p>可以通过全局请求响应拦截器,登录响应后自动设置 Cookie 到本地存储、发请求时自动取出 Cookie 并设置到请求头中。</p><h3 id="5、开发规范"><a href="#5、开发规范" class="headerlink" title="5、开发规范"></a><strong>5、开发规范</strong></h3><p>编写 <strong>typescript</strong> 数据模型,可以利用编辑器自动提示和校验,提升规范性。</p><p>可以利用 CodeGeex 智能编程助手,根据示例数据自动生成 TypeScript 类型。</p>]]></content>
<categories>
<category>项目</category>
</categories>
<tags>
<tag>小程序</tag>
</tags>
</entry>
<entry>
<title>力扣100题-链表</title>
<link href="/2024/08/10/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E9%93%BE%E8%A1%A8/"/>
<url>/2024/08/10/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E9%93%BE%E8%A1%A8/</url>
<content type="html"><![CDATA[<h3 id="1-相交链表"><a href="#1-相交链表" class="headerlink" title="1.相交链表"></a>1.相交链表</h3><ul><li>描述:给你两个单链表的头节点 <code>headA</code> 和 <code>headB</code> ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 <code>null</code> 。</li></ul><h4 id="思路一:"><a href="#思路一:" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li><p>分别设置两个指针指向两个链表的表头,同时往后遍历,一旦到达链表尾就跳到另一个链表头开始遍历。如果两个链表存在交点,两个指针到达交点时经过的路径是相等的,恰好相遇。如果两个链表不存在交点,那么就分别遍历了两个链表的长度,A和B都是null,返回null。</p></li><li><p>代码一:</p></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-comment"># Definition for singly-linked list.</span><br><span class="hljs-comment"># class ListNode:</span><br><span class="hljs-comment"># def __init__(self, x):</span><br><span class="hljs-comment"># self.val = x</span><br><span class="hljs-comment"># self.next = None</span><br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">getIntersectionNode</span>(<span class="hljs-params">self, headA: ListNode, headB: ListNode</span>) -> <span class="hljs-type">Optional</span>[ListNode]:<br> A = headA<br> B = headB<br> <span class="hljs-keyword">while</span> A != B:<br> A = A.<span class="hljs-built_in">next</span> <span class="hljs-keyword">if</span> A <span class="hljs-keyword">else</span> headB //如果A不是null就跳到<span class="hljs-built_in">next</span>,否则跳到链表B<br> B = B.<span class="hljs-built_in">next</span> <span class="hljs-keyword">if</span> B <span class="hljs-keyword">else</span> headA<br> <span class="hljs-keyword">return</span> A<br></code></pre></td></tr></table></figure><ul><li>代码二:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-comment"># Definition for singly-linked list.</span><br><span class="hljs-comment"># class ListNode:</span><br><span class="hljs-comment"># def __init__(self, x):</span><br><span class="hljs-comment"># self.val = x</span><br><span class="hljs-comment"># self.next = None</span><br><br><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">getIntersectionNode</span>(<span class="hljs-params">self, headA: ListNode, headB: ListNode</span>) -> <span class="hljs-type">Optional</span>[ListNode]:<br> A = headA<br> B = headB<br> <span class="hljs-keyword">while</span> A != B:<br> <span class="hljs-keyword">if</span> A: //简单直接的写法<br> A = A.<span class="hljs-built_in">next</span><br> <span class="hljs-keyword">else</span>:<br> A = headB<br> <span class="hljs-keyword">if</span> B:<br> B = B.<span class="hljs-built_in">next</span><br> <span class="hljs-keyword">else</span>:<br> B = headA<br> <span class="hljs-keyword">return</span> A<br></code></pre></td></tr></table></figure><h3 id="2-反转链表"><a href="#2-反转链表" class="headerlink" title="2.反转链表"></a>2.反转链表</h3><ul><li>描述:给你单链表的头节点 <code>head</code> ,请你反转链表,并返回反转后的链表。</li></ul><h4 id="思路一:-1"><a href="#思路一:-1" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>从链表头开始,对链表的节点进行逐个的翻转。除了cur指向当前的指针,增加pre指向前一个节点,tmp记录下一个节点</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">reverseList</span>(<span class="hljs-params">self, head: <span class="hljs-type">Optional</span>[ListNode]</span>) -> <span class="hljs-type">Optional</span>[ListNode]:<br> pre = <span class="hljs-literal">None</span> //设置为空指针<span class="hljs-string">"None"</span><br> cur = head<br> <span class="hljs-keyword">while</span> cur:<br> tmp = cur.<span class="hljs-built_in">next</span><br> cur.<span class="hljs-built_in">next</span> = pre<br> pre = cur<br> cur = tmp<br> <span class="hljs-keyword">return</span> pre<br></code></pre></td></tr></table></figure><h3 id="3-回文链表"><a href="#3-回文链表" class="headerlink" title="3.回文链表"></a>3.回文链表</h3><ul><li>描述:给你一个单链表的头节点 <code>head</code> ,请你判断该链表是否为回文链表。如果是,返回 <code>true</code> ;否则,返回 <code>false</code> 。</li></ul><h4 id="思路一:-2"><a href="#思路一:-2" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>申请新空间,用另一个链表存储反转后的链表,逐个遍历比较两个链表是否相同即可。在python中可以用一个新列表存储链表里的数字,然后直接与它的反转进行比较。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">isPalindrome</span>(<span class="hljs-params">self, head: <span class="hljs-type">Optional</span>[ListNode]</span>) -> <span class="hljs-built_in">bool</span>:<br> vals = [] //创建空列表<br> cur = head<br> <span class="hljs-keyword">while</span> cur:<br> vals.append(cur.val)<br> cur = cur.<span class="hljs-built_in">next</span><br> <span class="hljs-keyword">return</span> vals == vals[::-<span class="hljs-number">1</span>] <br> //列表切片操作<span class="hljs-built_in">list</span>[start:end:step],-<span class="hljs-number">1</span>表示将 vals 列表中的元素逆序排列<br></code></pre></td></tr></table></figure><h4 id="思路二:"><a href="#思路二:" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>先使用快慢指针找到链表的中点,反转后半部分链表,同时得到原链表尾的位置,同时往中间走进行比较。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">middleNode</span>(<span class="hljs-params">self, head</span>):<br> slow = head<br> fast = head<br> <span class="hljs-keyword">while</span> fast <span class="hljs-keyword">and</span> fast.<span class="hljs-built_in">next</span>:<br> slow = slow.<span class="hljs-built_in">next</span><br> fast = fast.<span class="hljs-built_in">next</span>.<span class="hljs-built_in">next</span><br> <span class="hljs-keyword">return</span> slow<br> <br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">reverseList</span>(<span class="hljs-params">self, head</span>):<br> pre = <span class="hljs-literal">None</span><br> cur = head<br> <span class="hljs-keyword">while</span> cur:<br> tmp = cur.<span class="hljs-built_in">next</span><br> cur.<span class="hljs-built_in">next</span> = pre<br> pre = cur<br> cur = tmp<br> <span class="hljs-keyword">return</span> pre<br><br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">isPalindrome</span>(<span class="hljs-params">self, head: <span class="hljs-type">Optional</span>[ListNode]</span>) -> <span class="hljs-built_in">bool</span>:<br> <span class="hljs-keyword">if</span> head <span class="hljs-keyword">is</span> <span class="hljs-literal">None</span>:<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span><br> mid = self.middleNode(head)<br> head2 = self.reverseList(mid)<br> <span class="hljs-keyword">while</span> head2:<br> <span class="hljs-keyword">if</span> head.val != head2.val:<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span><br> head = head.<span class="hljs-built_in">next</span><br> head2 = head2.<span class="hljs-built_in">next</span><br> <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span><br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>力扣</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>力扣100题-矩阵</title>
<link href="/2024/08/07/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E7%9F%A9%E9%98%B5/"/>
<url>/2024/08/07/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E7%9F%A9%E9%98%B5/</url>
<content type="html"><![CDATA[<h3 id="1-矩阵置零"><a href="#1-矩阵置零" class="headerlink" title="1.矩阵置零"></a>1.矩阵置零</h3><ul><li>描述:给定一个 <code>*m* x *n*</code> 的矩阵,如果一个元素为 <strong>0</strong> ,则将其所在行和列的所有元素都设为 <strong>0</strong> 。请使用 <strong><a href="http://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95">原地</a></strong> 算法<strong>。</strong></li></ul><h4 id="思路一:"><a href="#思路一:" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>使用两个标记数组,,用矩阵的第一行和第一列代替两个标记数组,分别表示每一行,每一列是否要置为零,遍历矩阵,更新标记数组,再用标记数组来更新矩阵。达到O(1)的额外空间。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">setZeroes</span>(<span class="hljs-params">self, matrix: <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]]</span>) -> <span class="hljs-literal">None</span>:<br> m = <span class="hljs-built_in">len</span>(matrix)<br> n = <span class="hljs-built_in">len</span>(matrix[<span class="hljs-number">0</span>])<br> <span class="hljs-comment"># 先特殊处理第一行和第一列</span><br> flag_col0 = <span class="hljs-built_in">any</span>(matrix[i][<span class="hljs-number">0</span>] == <span class="hljs-number">0</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(m))<br> flag_row0 = <span class="hljs-built_in">any</span>(matrix[<span class="hljs-number">0</span>][i] == <span class="hljs-number">0</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n))<br><span class="hljs-comment"># 遍历矩阵,把0存在对应的第一行和第一列上</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, m):<br> <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, n):<br> <span class="hljs-keyword">if</span> matrix[i][j] == <span class="hljs-number">0</span>:<br> matrix[i][<span class="hljs-number">0</span>] = matrix[<span class="hljs-number">0</span>][j] = <span class="hljs-number">0</span><br> <span class="hljs-comment">#更新矩阵</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, m):<br> <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, n):<br> <span class="hljs-keyword">if</span> matrix[i][<span class="hljs-number">0</span>] == <span class="hljs-number">0</span> <span class="hljs-keyword">or</span> matrix[<span class="hljs-number">0</span>][j] == <span class="hljs-number">0</span>:<br> matrix[i][j] = <span class="hljs-number">0</span><br> <span class="hljs-comment"># 回过头更新第一行和第一列</span><br> <span class="hljs-keyword">if</span> flag_col0:<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(m):<br> matrix[i][<span class="hljs-number">0</span>] = <span class="hljs-number">0</span><br> <span class="hljs-keyword">if</span> flag_row0:<br> <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> matrix[<span class="hljs-number">0</span>][j] = <span class="hljs-number">0</span><br></code></pre></td></tr></table></figure><h3 id="2-螺旋矩阵"><a href="#2-螺旋矩阵" class="headerlink" title="2.螺旋矩阵"></a>2.螺旋矩阵</h3><ul><li>描述:给你一个 <code>m</code> 行 <code>n</code> 列的矩阵 <code>matrix</code> ,请按照 <strong>顺时针螺旋顺序</strong> ,返回矩阵中的所有元素。</li></ul><h4 id="思路一:-1"><a href="#思路一:-1" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>发现顺序是有一定规律的,即都是从左到右,从上到下,从右到左,从下到上的不断循环,可以设置四个边界,一旦某两个相对的边界越过后,循环结束</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">spiralOrder</span>(<span class="hljs-params">self, matrix: <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]]</span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]:<br> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> matrix: <span class="hljs-keyword">return</span> []<br> n = <span class="hljs-built_in">len</span>(matrix)<br> m = <span class="hljs-built_in">len</span>(matrix[<span class="hljs-number">0</span>])<br> l, r, t, b = <span class="hljs-number">0</span>, m - <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, n - <span class="hljs-number">1</span><br> res = <span class="hljs-built_in">list</span>()<br> <span class="hljs-keyword">while</span> <span class="hljs-literal">True</span>:<br> <span class="hljs-comment"># 从左到右</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(l, r + <span class="hljs-number">1</span>):<br> res.append(matrix[t][i])<br> t += <span class="hljs-number">1</span><br> <span class="hljs-keyword">if</span> t > b:<br> <span class="hljs-keyword">break</span><br> <span class="hljs-comment"># 从上到下</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(t, b + <span class="hljs-number">1</span>):<br> res.append(matrix[i][r])<br> r -= <span class="hljs-number">1</span><br> <span class="hljs-keyword">if</span> r < l:<br> <span class="hljs-keyword">break</span><br> <span class="hljs-comment"># 从右到左</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(r, l - <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>):<br> res.append(matrix[b][i])<br> b -= <span class="hljs-number">1</span><br> <span class="hljs-keyword">if</span> b < t:<br> <span class="hljs-keyword">break</span><br> <span class="hljs-comment"># 从下到上</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(b, t - <span class="hljs-number">1</span>, -<span class="hljs-number">1</span>):<br> res.append(matrix[i][l])<br> l += <span class="hljs-number">1</span><br> <span class="hljs-keyword">if</span> l > r:<br> <span class="hljs-keyword">break</span><br> <span class="hljs-keyword">return</span> res<br></code></pre></td></tr></table></figure><h3 id="3-旋转图像"><a href="#3-旋转图像" class="headerlink" title="3.旋转图像"></a>3.旋转图像</h3><ul><li><p>描述:给定一个 <em>n</em> × <em>n</em> 的二维矩阵 <code>matrix</code> 表示一个图像。请你将图像顺时针旋转 90 度。</p><p>你必须在**<a href="https://baike.baidu.com/item/%E5%8E%9F%E5%9C%B0%E7%AE%97%E6%B3%95"> 原地</a>** 旋转图像,这意味着你需要直接修改输入的二维矩阵。<strong>请不要</strong> 使用另一个矩阵来旋转图像。</p></li></ul><h4 id="思路一:-2"><a href="#思路一:-2" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>可以发现先对矩阵进行<strong>上下翻转</strong>再进行<strong>按对角线翻转</strong>即可实现顺时针的旋转90度</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">rotate</span>(<span class="hljs-params">self, matrix: <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]]</span>) -> <span class="hljs-literal">None</span>:<br> n = <span class="hljs-built_in">len</span>(matrix)<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n // <span class="hljs-number">2</span>): <span class="hljs-comment"># //表示整除</span><br> <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> matrix[i][j], matrix[n - i - <span class="hljs-number">1</span>][j] = matrix[n-i-<span class="hljs-number">1</span>][j], matrix[i][j]<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(i): <span class="hljs-comment">#按对角线进行翻转</span><br> matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]<br></code></pre></td></tr></table></figure><h3 id="4-搜索二维矩阵"><a href="#4-搜索二维矩阵" class="headerlink" title="4.搜索二维矩阵||"></a>4.搜索二维矩阵||</h3><ul><li>描述:编写一个高效的算法来搜索 <code>*m* x *n*</code> 矩阵 <code>matrix</code> 中的一个目标值 <code>target</code> 。该矩阵具有以下特性:<ul><li>每行的元素从左到右升序排列。</li><li>每列的元素从上到下升序排列。</li></ul></li></ul><h4 id="思路一:-3"><a href="#思路一:-3" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>由于每行都是有序的,可以利用bisect模块对每行进行二分查找,时间复杂度为<em>O</em>(<em>m</em>log<em>n</em>)</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">searchMatrix</span>(<span class="hljs-params">self, matrix: <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]], target: <span class="hljs-built_in">int</span></span>) -> <span class="hljs-built_in">bool</span>:<br> <span class="hljs-keyword">for</span> row <span class="hljs-keyword">in</span> matrix:<br> idx = bisect_left(row, target)<br> <span class="hljs-keyword">if</span> idx < <span class="hljs-built_in">len</span>(row) <span class="hljs-keyword">and</span> row[idx] == target: <span class="hljs-comment"># 当target大于所有这一行的数,idx为len(row),会导致索引越界,需要提前判读</span><br> <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span><br> <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span><br></code></pre></td></tr></table></figure><h4 id="思路二:"><a href="#思路二:" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>思路一中没有利用好每一列之间也是升序的。可以从右上角(0,n-1)的元素tmp开始搜索,当target<tmp时,那么tmp所在的列都一定比target大,y -= 1;当target>tmp时,tmp所在的行都比target小,x += 1。相当于一个Z字型走法,完美地利用了两个升序条件,时间复杂度为O(m+n)。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">searchMatrix</span>(<span class="hljs-params">self, matrix: <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]], target: <span class="hljs-built_in">int</span></span>) -> <span class="hljs-built_in">bool</span>:<br> m = <span class="hljs-built_in">len</span>(matrix)<br> n = <span class="hljs-built_in">len</span>(matrix[<span class="hljs-number">0</span>])<br> x, y = <span class="hljs-number">0</span>, n - <span class="hljs-number">1</span><br> <span class="hljs-keyword">while</span> x < m <span class="hljs-keyword">and</span> y >= <span class="hljs-number">0</span>: <span class="hljs-comment"># 设置边界</span><br> <span class="hljs-keyword">if</span> matrix[x][y] == target:<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">True</span><br> <span class="hljs-keyword">if</span> matrix[x][y] < target:<br> x += <span class="hljs-number">1</span><br> <span class="hljs-keyword">else</span>:<br> y -= <span class="hljs-number">1</span><br> <span class="hljs-keyword">return</span> <span class="hljs-literal">False</span><br></code></pre></td></tr></table></figure><h3 id="小节:"><a href="#小节:" class="headerlink" title="小节:"></a>小节:</h3><ul><li>矩阵一般在于空间的优化,在原地进行操作,那么就要对要求的操作进行找规律或是直接利用原先矩阵的空间</li><li>也会涉及到旋转,翻转等操作,要找规律变换</li><li>矩阵也相当于一个二维数组,进行一些数组操作</li></ul>]]></content>
<categories>
<category>力扣</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>力扣100题-普通数组</title>
<link href="/2024/08/07/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E6%99%AE%E9%80%9A%E6%95%B0%E7%BB%84/"/>
<url>/2024/08/07/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E6%99%AE%E9%80%9A%E6%95%B0%E7%BB%84/</url>
<content type="html"><![CDATA[<h3 id="1-最大子数组和"><a href="#1-最大子数组和" class="headerlink" title="1.最大子数组和"></a>1.最大子数组和</h3><ul><li><p>描述:给你一个整数数组 <code>nums</code> ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。</p><p><strong>子数组</strong>是数组中的一个连续部分</p></li></ul><h4 id="思路一:"><a href="#思路一:" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>动态规划,dp[i]表示以i为结尾的连续数组的最大和。当dp[i-1]<=0时,dp[i] = nums[i],else dp[i] = dp[i-1]+nums[i]。由于dp[i]只根据dp[i-1]即可得出可以用一个变量pre来表示,节约空间</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">maxSubArray</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-built_in">int</span>:<br> n = <span class="hljs-built_in">len</span>(nums)<br> pre = nums[<span class="hljs-number">0</span>]<br> ans = nums[<span class="hljs-number">0</span>] <span class="hljs-comment"># n >= 1才可以这样写</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, n):<br> <span class="hljs-keyword">if</span> pre <= <span class="hljs-number">0</span>:<br> pre = nums[i]<br> <span class="hljs-keyword">else</span>:<br> pre = pre+nums[i]<br> ans = <span class="hljs-built_in">max</span>(ans, pre) <br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h4 id="思路二:"><a href="#思路二:" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>前缀和。求连续数组的和的最大值,很容易想到前缀和,那么问题就转化为股票出卖时间那道贪心题,边遍历边更新前缀和数组,存储最小的前缀和数组,然后取它们的差,在这个过程中不断更新答案</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">maxSubArray</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-built_in">int</span>:<br> n = <span class="hljs-built_in">len</span>(nums)<br> pre_sum = pre_min_sum = <span class="hljs-number">0</span><br> ans = - inf<br> <span class="hljs-keyword">for</span> x <span class="hljs-keyword">in</span> nums:<br> pre_sum += x <span class="hljs-comment"># 更新当前的前缀和</span><br> ans = <span class="hljs-built_in">max</span>(ans, pre_sum - pre_min_sum)<br> pre_min_sum = <span class="hljs-built_in">min</span>(pre_min_sum, pre_sum) <span class="hljs-comment"># 更新最小的前缀和</span><br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h3 id="2-合并区间"><a href="#2-合并区间" class="headerlink" title="2.合并区间"></a>2.合并区间</h3><ul><li>描述:以数组 <code>intervals</code> 表示若干个区间的集合,其中单个区间为 <code>intervals[i] = [starti, endi]</code> 。请你合并所有重叠的区间,并返回 <em>一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间</em> 。</li></ul><h4 id="思路一:-1"><a href="#思路一:-1" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>思路很清晰,按左端点进行排序,当当前的左端点在前一个的右端点的前面,就说明可以尝试进行合并,反之,直接作为一个新的区间加入到答案中</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">merge</span>(<span class="hljs-params">self, intervals: <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]]</span>) -> <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]]:<br> intervals.sort(key=<span class="hljs-keyword">lambda</span> x:x[<span class="hljs-number">0</span>]) <span class="hljs-comment"># 按左端点进行升序排序</span><br> ans = [intervals[<span class="hljs-number">0</span>]] <span class="hljs-comment"># 特殊处理第一个区间,也可以放到for里,加个判断即可</span><br> n = <span class="hljs-built_in">len</span>(intervals)<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, n):<br> <span class="hljs-keyword">if</span> intervals[i][<span class="hljs-number">0</span>] <= ans[-<span class="hljs-number">1</span>][<span class="hljs-number">1</span>]:<br> ans[-<span class="hljs-number">1</span>][<span class="hljs-number">1</span>] = <span class="hljs-built_in">max</span>(ans[-<span class="hljs-number">1</span>][<span class="hljs-number">1</span>], intervals[i][<span class="hljs-number">1</span>])<br> <span class="hljs-keyword">else</span>:<br> ans.append(intervals[i])<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h3 id="3-轮转数组"><a href="#3-轮转数组" class="headerlink" title="3.轮转数组"></a>3.轮转数组</h3><ul><li>描述:给定一个整数数组 <code>nums</code>,将数组中的元素向右轮转 <code>k</code> 个位置,其中 <code>k</code> 是非负数。</li></ul><h4 id="思路一:-2"><a href="#思路一:-2" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li><p>通过三次翻转数组可以实现不增加额外空间的情况下实现轮转数组,很巧妙!</p></li><li><p>代码</p></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">rotate</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>], k: <span class="hljs-built_in">int</span></span>) -> <span class="hljs-literal">None</span>:<br> <span class="hljs-string">"""</span><br><span class="hljs-string"> Do not return anything, modify nums in-place instead.</span><br><span class="hljs-string"> """</span><br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">reverse</span>(<span class="hljs-params">i: <span class="hljs-built_in">int</span>, j: <span class="hljs-built_in">int</span></span>) -> <span class="hljs-literal">None</span>: <span class="hljs-comment"># 手写翻转数组</span><br> <span class="hljs-keyword">while</span> i < j:<br> nums[i], nums[j] = nums[j], nums[i]<br> i += <span class="hljs-number">1</span><br> j -= <span class="hljs-number">1</span><br> n = <span class="hljs-built_in">len</span>(nums)<br> k = k % n<br> reverse(<span class="hljs-number">0</span>, n-<span class="hljs-number">1</span>)<br> reverse(<span class="hljs-number">0</span>, k-<span class="hljs-number">1</span>)<br> reverse(k, n-<span class="hljs-number">1</span>)<br></code></pre></td></tr></table></figure><h3 id="4-除自身以外的数组乘积"><a href="#4-除自身以外的数组乘积" class="headerlink" title="4.除自身以外的数组乘积"></a>4.除自身以外的数组乘积</h3><ul><li><p>描述:给你一个整数数组 <code>nums</code>,返回 数组 <code>answer</code> ,其中 <code>answer[i]</code> 等于 <code>nums</code> 中除 <code>nums[i]</code> 之外其余各元素的乘积 。</p><p>题目数据 <strong>保证</strong> 数组 <code>nums</code>之中任意元素的全部前缀元素和后缀的乘积都在 <strong>32 位</strong> 整数范围内。</p><p>请 <strong>不要使用除法,</strong>且在 <code>O(n)</code> 时间复杂度内完成此题。</p></li></ul><h4 id="思路一:-3"><a href="#思路一:-3" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li><p>关键在于不能使用除法,那么就通过位置i的前缀和后缀数组相乘来得到答案。注意左右边界的处理。时间复杂度为O[N],空间复杂度为O[N]</p></li><li><p>代码:</p></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">productExceptSelf</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]:<br> n = <span class="hljs-built_in">len</span>(nums)<br> pre = [<span class="hljs-number">1</span>] * n<br> suf = [<span class="hljs-number">1</span>] * n <br> <span class="hljs-comment"># 前缀数组和后缀数组的初始化</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, n):<br> pre[i] = pre[i-<span class="hljs-number">1</span>] * nums[i-<span class="hljs-number">1</span>]<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n-<span class="hljs-number">2</span>, -<span class="hljs-number">1</span>, -<span class="hljs-number">1</span>):<br> suf[i] = suf[i+<span class="hljs-number">1</span>] * nums[i+<span class="hljs-number">1</span>]<br> ans = <span class="hljs-built_in">list</span>()<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> ans.append(pre[i] * suf[i])<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h4 id="思路二:-1"><a href="#思路二:-1" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>在思路一的基础上优化空间,其中的前缀数组可以隐藏进最后的遍历中,减少了空间的浪费</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">productExceptSelf</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]:<br> n = <span class="hljs-built_in">len</span>(nums)<br> suf = [<span class="hljs-number">1</span>] * n <br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n-<span class="hljs-number">2</span>, -<span class="hljs-number">1</span>, -<span class="hljs-number">1</span>):<br> suf[i] = suf[i+<span class="hljs-number">1</span>] * nums[i+<span class="hljs-number">1</span>]<br> ans = <span class="hljs-built_in">list</span>()<br> pre = <span class="hljs-number">1</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> ans.append(pre * suf[i])<br> pre *= nums[i]<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h3 id="5-缺失的第一个正数"><a href="#5-缺失的第一个正数" class="headerlink" title="5.缺失的第一个正数"></a>5.缺失的第一个正数</h3><ul><li><p>描述:给你一个未排序的整数数组 <code>nums</code> ,请你找出其中没有出现的最小的正整数。</p><p>请你实现时间复杂度为 <code>O(n)</code> 并且只使用常数级别额外空间的解决方案。</p></li></ul><h4 id="思路一:-4"><a href="#思路一:-4" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>找没出现过的数可以想到哈希,但是要结合常数级别的额外空间可以想到原地哈希。有题目可知答案的范围为[1,N+1],那么先对负数进行处理,把他们转化为n+1,再遍历数组,若当前的数<=n,就把它的减一作为下标的nums[i-1]修改为-nums[i-1],用负数来标记整个数出现过。那么最后只需要遍历数组,第一个正数就是答案了,或者就是n+1。非常妙的在原地实现了哈希表</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">firstMissingPositive</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-built_in">int</span>:<br> n = <span class="hljs-built_in">len</span>(nums)<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n): <span class="hljs-comment"># 预处理负数</span><br> <span class="hljs-keyword">if</span> nums[i] <= <span class="hljs-number">0</span>:<br> nums[i] = n + <span class="hljs-number">1</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> c = <span class="hljs-built_in">abs</span>(nums[i])<br> <span class="hljs-keyword">if</span> c <= n:<br> nums[c - <span class="hljs-number">1</span>] = -<span class="hljs-built_in">abs</span>(nums[c - <span class="hljs-number">1</span>]) <span class="hljs-comment"># 关键语句</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> <span class="hljs-keyword">if</span> nums[i] > <span class="hljs-number">0</span>:<br> <span class="hljs-keyword">return</span> i + <span class="hljs-number">1</span><br> <span class="hljs-keyword">return</span> n + <span class="hljs-number">1</span><br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>力扣</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>力扣100题-子串</title>
<link href="/2024/08/06/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E5%AD%90%E4%B8%B2/"/>
<url>/2024/08/06/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E5%AD%90%E4%B8%B2/</url>
<content type="html"><![CDATA[<h3 id="1-和为K的子数组"><a href="#1-和为K的子数组" class="headerlink" title="1.和为K的子数组"></a>1.和为K的子数组</h3><ul><li><p>描述:给你一个整数数组 <code>nums</code> 和一个整数 <code>k</code> ,请你统计并返回 <em>该数组中和为 <code>k</code> 的子数组的个数</em> 。</p><p>子数组是数组中元素的连续非空序列。</p></li></ul><h4 id="思路一:"><a href="#思路一:" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>连续序列加上求和,自然而然想到使用前缀和,由于数可能是正0负,求子数组的个数,可以依赖于哈希表,遍历前缀和数组,通过-k去找之前是否出现过sj-k的前缀和数字,就相当于有多少个区间是满足条件的。以O[N]的复杂度解决了区间的查找,很巧妙。还有当只有一个元素的数组就这一个元素满足条件时,cnt[0] = 1是很重要的初始化。</li><li>代码</li></ul><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs pyhton">class Solution:<br> def subarraySum(self, nums: List[int], k: int) -> int:<br> n = len(nums)<br> sum = [0]*(n+1)<br> for i in range(n):<br> sum[i+1] = sum[i] + nums[i] # 求前缀和数组<br> cnt = defaultdict(int) # cnt初始化为0<br> ans = 0<br> for sj in sum:<br> ans += cnt[sj - k] #先求解,再把数放进哈希表<br> cnt[sj] += 1<br> return ans<br></code></pre></td></tr></table></figure><h3 id="2-滑动窗口的最大值"><a href="#2-滑动窗口的最大值" class="headerlink" title="2.滑动窗口的最大值"></a>2.滑动窗口的最大值</h3><ul><li><p>描述:给你一个整数数组 <code>nums</code>,有一个大小为 <code>k</code> 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 <code>k</code> 个数字。滑动窗口每次只向右移动一位。</p><p>返回 <em>滑动窗口中的最大值</em> 。</p></li></ul><h4 id="思路一:-1"><a href="#思路一:-1" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>优先队列,要求滑动窗口内的最大值,考虑快速可以排序的结构,即优先队列,每次移动,需要考虑当前的最大值是否在合法范围内,时间复杂度为o[NlogN]</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">maxSlidingWindow</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>], k: <span class="hljs-built_in">int</span></span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]:<br> n = <span class="hljs-built_in">len</span>(nums)<br> q = [(-nums[i], i) <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(k)] <span class="hljs-comment"># python默认小根堆,所以要存负数</span><br> heapq.heapify(q) <span class="hljs-comment"># 小根堆初始化</span><br> ans = <span class="hljs-built_in">list</span>()<br> ans.append(-q[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>])<br><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(k, n):<br> heapq.heappush(q, (-nums[i], i))<br> <span class="hljs-keyword">while</span> q[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>] <= i - k: <span class="hljs-comment"># 使最大值要在合法范围内</span><br> heapq.heappop(q)<br> ans.append(-q[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>])<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h4 id="思路二:"><a href="#思路二:" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>单调队列。使用优先队列时,每个数字都要反复参加多次排序。如果nums[i] < nums[j]且i<j,那么nums[i]其实肯定不会成为答案,可以直接删掉。也就是说可以维护一个严格递减的队列来实现快速找最大值。由于队列队首可能会出队,队尾要入队,所以采取双向队列。</li><li>代码</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">maxSlidingWindow</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>], k: <span class="hljs-built_in">int</span></span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]:<br> n = <span class="hljs-built_in">len</span>(nums)<br> q = collections.deque() <span class="hljs-comment"># 双向队列初始化</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(k): <span class="hljs-comment"># 先对第一个窗口初始化</span><br> <span class="hljs-keyword">while</span> q <span class="hljs-keyword">and</span> nums[i] >= nums[q[-<span class="hljs-number">1</span>]]:<br> q.pop()<br> q.append(i) <br> ans = [nums[q[<span class="hljs-number">0</span>]]]<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(k, n):<br> <span class="hljs-keyword">while</span> q <span class="hljs-keyword">and</span> nums[i] >= nums[q[-<span class="hljs-number">1</span>]]: <span class="hljs-comment"># 淘汰之前的小于等于当前的数</span><br> q.pop()<br> q.append(i)<br> <span class="hljs-keyword">while</span> q[<span class="hljs-number">0</span>] <= i - k:<span class="hljs-comment"># 使队首在合法范围内</span><br> q.popleft()<br> ans.append(nums[q[<span class="hljs-number">0</span>]])<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h4 id="思路三:"><a href="#思路三:" class="headerlink" title="思路三:"></a>思路三:</h4><ul><li>分块,把整个数组以k为单位进行分组,那么对于每个窗口的起始位置i,它的一般情况会横跨两个区间,可以分别设置两个数组prefixMax和suffixMax来存储当前下标在块内的前置和后置的最大值,实现复杂度为O[N]。那么对于起始位置i的窗口内的最大值就是suffixMax[i]和prefixMax[i+k-1]中的较大值</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">maxSlidingWindow</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>], k: <span class="hljs-built_in">int</span></span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]:<br> n = <span class="hljs-built_in">len</span>(nums)<br> prefixMax, suffixMax = [<span class="hljs-number">0</span>]*n, [<span class="hljs-number">0</span>]*n<br> <span class="hljs-comment"># 初始化前缀和和后缀和数组,考虑前后的边界情况</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> <span class="hljs-keyword">if</span> i % k == <span class="hljs-number">0</span>:<br> prefixMax[i] = nums[i]<br> <span class="hljs-keyword">else</span>:<br> prefixMax[i] = <span class="hljs-built_in">max</span>(prefixMax[i-<span class="hljs-number">1</span>], nums[i])<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n-<span class="hljs-number">1</span>, -<span class="hljs-number">1</span>, -<span class="hljs-number">1</span>):<br> <span class="hljs-keyword">if</span> i == n-<span class="hljs-number">1</span> <span class="hljs-keyword">or</span> (i+<span class="hljs-number">1</span>) % k == <span class="hljs-number">0</span>:<br> suffixMax[i] = nums[i]<br> <span class="hljs-keyword">else</span>:<br> suffixMax[i] = <span class="hljs-built_in">max</span>(suffixMax[i+<span class="hljs-number">1</span>], nums[i])<br><br> ans = <span class="hljs-built_in">list</span>()<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n-k+<span class="hljs-number">1</span>):<br> ans.append(<span class="hljs-built_in">max</span>(suffixMax[i], prefixMax[i+k-<span class="hljs-number">1</span>]))<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h3 id="3-最小覆盖子串"><a href="#3-最小覆盖子串" class="headerlink" title="3.最小覆盖子串"></a>3.最小覆盖子串</h3><ul><li>描述:给你一个字符串 <code>s</code> 、一个字符串 <code>t</code> 。返回 <code>s</code> 中涵盖 <code>t</code> 所有字符的最小子串。如果 <code>s</code> 中不存在涵盖 <code>t</code> 所有字符的子串,则返回空字符串 <code>""</code> 。</li></ul><h4 id="思路一:-2"><a href="#思路一:-2" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>双指针,先固定左指针,遍历移动右指针直到满足涵盖t,(判断涵盖通过Counter函数比较实现),一旦实现,就移动左指针来尽可能地缩小子串范围。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">minWindow</span>(<span class="hljs-params">self, s: <span class="hljs-built_in">str</span>, t: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">str</span>:<br> n = <span class="hljs-built_in">len</span>(s)<br> m = <span class="hljs-built_in">len</span>(t)<br> cnt_s = Counter()<br> cnt_t = Counter(t) <span class="hljs-comment">#字母出现次数计数器</span><br> l = <span class="hljs-number">0</span><br> ans_left, ans_right = -<span class="hljs-number">1</span>, n<br> <span class="hljs-keyword">for</span> r, c <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(s):<br> cnt_s[c] += <span class="hljs-number">1</span><br> <span class="hljs-keyword">while</span> cnt_s >= cnt_t: <span class="hljs-comment"># 出现合法子串,进而缩左端点</span><br> <span class="hljs-keyword">if</span> r - l < ans_right - ans_left:<br> ans_left, ans_right = l, r <br> cnt_s[s[l]] -= <span class="hljs-number">1</span><br> l += <span class="hljs-number">1</span><br> <span class="hljs-keyword">if</span> ans_left == -<span class="hljs-number">1</span>: <span class="hljs-comment">#从未更新过答案,直接返回空字符串</span><br> <span class="hljs-keyword">return</span> <span class="hljs-string">""</span><br> <span class="hljs-keyword">return</span> s[ans_left: ans_right + <span class="hljs-number">1</span>]<br></code></pre></td></tr></table></figure><h3 id="小节:"><a href="#小节:" class="headerlink" title="小节:"></a>小节:</h3><ul><li>子串的应用范围还是比较广的,主要是要求连续,那么会跟前缀数组后缀数组,双指针这些联系比较紧密</li><li>分析题目的限制条件,寻找合理的结构或者算法取贪心解决,降低时间复杂度</li></ul>]]></content>
<categories>
<category>力扣</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>力扣100题-滑动窗口</title>
<link href="/2024/08/05/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3/"/>
<url>/2024/08/05/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3/</url>
<content type="html"><![CDATA[<h3 id="1-无重复字符的最长子串"><a href="#1-无重复字符的最长子串" class="headerlink" title="1.无重复字符的最长子串"></a>1.无重复字符的最长子串</h3><ul><li>描述:给定一个字符串 <code>s</code> ,请你找出其中不含有重复字符的 <strong>最长 子串</strong> 的长度。</li></ul><h4 id="思路一:"><a href="#思路一:" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>首先子串是连续的,可以先固定左端点,右端点在数组里遍历,当右端点的数出现过(哈希表),就移动对应的左端点直到满足右端点没有出现过。这样就遍历了所有的可能性,得出最大的ans。这是一个变长的滑动窗口。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">lengthOfLongestSubstring</span>(<span class="hljs-params">self, s: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-built_in">int</span>:<br> n = <span class="hljs-built_in">len</span>(s)<br> ans = <span class="hljs-number">0</span><br> <span class="hljs-built_in">hash</span> = <span class="hljs-built_in">set</span>() <span class="hljs-comment"># 哈希表</span><br> l = <span class="hljs-number">0</span><br> <span class="hljs-keyword">for</span> r, cur <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(s):<br> <span class="hljs-keyword">while</span> cur <span class="hljs-keyword">in</span> <span class="hljs-built_in">hash</span>: <span class="hljs-comment">#使[l,r]没有重复字符</span><br> <span class="hljs-built_in">hash</span>.remove(s[l])<br> l += <span class="hljs-number">1</span><br> <span class="hljs-built_in">hash</span>.add(cur)<br> ans = <span class="hljs-built_in">max</span>(ans, r - l + <span class="hljs-number">1</span>)<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h3 id="2-找到字符串中所有字母异位词"><a href="#2-找到字符串中所有字母异位词" class="headerlink" title="2.找到字符串中所有字母异位词"></a>2.找到字符串中所有字母异位词</h3><ul><li><p>描述:给定两个字符串 <code>s</code> 和 <code>p</code>,找到 <code>s</code> 中所有 <code>p</code> 的 <strong>异位词</strong> 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。</p><p><strong>异位词</strong> 指由相同字母重排列形成的字符串(包括相同的字符串)。</p></li></ul><h4 id="思路一:-1"><a href="#思路一:-1" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>由于p是确定的,这是一个定长的滑动窗口,用一个26大小的list来记录p,每一移动减少一个字母增加一个字母,再判断当前窗口是否和p一致即可。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">findAnagrams</span>(<span class="hljs-params">self, s: <span class="hljs-built_in">str</span>, p: <span class="hljs-built_in">str</span></span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]:<br> slen = <span class="hljs-built_in">len</span>(s)<br> plen = <span class="hljs-built_in">len</span>(p)<br> <span class="hljs-keyword">if</span> slen < plen:<br> <span class="hljs-keyword">return</span> []<br> s_count = [<span class="hljs-number">0</span>] * <span class="hljs-number">26</span><br> p_count = [<span class="hljs-number">0</span>] * <span class="hljs-number">26</span> <span class="hljs-comment">#list初始化</span><br> ans = <span class="hljs-built_in">list</span>()<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(plen):<br> s_count[<span class="hljs-built_in">ord</span>(s[i])-<span class="hljs-number">97</span>] += <span class="hljs-number">1</span><br> p_count[<span class="hljs-built_in">ord</span>(p[i])-<span class="hljs-number">97</span>] += <span class="hljs-number">1</span> <span class="hljs-comment">#对第一个plen的子串进行特殊处理</span><br> <span class="hljs-keyword">if</span> s_count == p_count:<br> ans.append(<span class="hljs-number">0</span>)<br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(plen, slen):<br> s_count[<span class="hljs-built_in">ord</span>(s[i - plen])-<span class="hljs-number">97</span>] -= <span class="hljs-number">1</span><br> s_count[<span class="hljs-built_in">ord</span>(s[i])-<span class="hljs-number">97</span>] += <span class="hljs-number">1</span> <span class="hljs-comment">#移出一个字母,移进一个字母</span><br> <span class="hljs-keyword">if</span> s_count == p_count:<br> ans.append(i-plen+<span class="hljs-number">1</span>)<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h3 id="小节:"><a href="#小节:" class="headerlink" title="小节:"></a>小节:</h3><ul><li>滑动窗口是指维护一个满足特殊条件的区间,可能是定长的或是变长的</li><li>重点是这个特殊条件,以上两个条件分别是没有重复字母(哈希表),判断是否是某个字符串的异位词(数组标记)</li><li>有点像双指针,是一种特殊的双指针策略,主要用于处理连续子数组或子字符串问题。第一题就是它通过维护一个动态的区间(窗口)来优化查找过程。</li></ul>]]></content>
<categories>
<category>力扣</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>力扣100题-双指针</title>
<link href="/2024/08/04/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E5%8F%8C%E6%8C%87%E9%92%88/"/>
<url>/2024/08/04/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E5%8F%8C%E6%8C%87%E9%92%88/</url>
<content type="html"><![CDATA[<h3 id="1-移动零"><a href="#1-移动零" class="headerlink" title="1.移动零"></a>1.移动零</h3><ul><li><p>描述:给定一个数组 <code>nums</code>,编写一个函数将所有 <code>0</code> 移动到数组的末尾,同时保持非零元素的相对顺序。</p><p><strong>请注意</strong> ,必须在不复制数组的情况下原地对数组进行操作。</p></li></ul><h4 id="思路一:"><a href="#思路一:" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>从左到右遍历数组,发现非零数就按序重写到原数组中,再在数组的后半截补全对应的0,实现了不构建新数组</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">moveZeroes</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-literal">None</span>:<br> <span class="hljs-string">"""</span><br><span class="hljs-string"> Do not return anything, modify nums in-place instead.</span><br><span class="hljs-string"> """</span><br> n = <span class="hljs-built_in">len</span>(nums)<br> j = <span class="hljs-number">0</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> <span class="hljs-keyword">if</span> nums[i] != <span class="hljs-number">0</span>:<br> nums[j] = nums[i]<br> j += <span class="hljs-number">1</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(j, n):<br> nums[i] = <span class="hljs-number">0</span><br></code></pre></td></tr></table></figure><h4 id="思路二:"><a href="#思路二:" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>有点神似快排,交换的条件是当前的数是非零的。左指针左边均是非零数,右指针到左指针为止皆是0(一般情况)</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">moveZeroes</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-literal">None</span>:<br> <span class="hljs-string">"""</span><br><span class="hljs-string"> Do not return anything, modify nums in-place instead.</span><br><span class="hljs-string"> """</span><br> n = <span class="hljs-built_in">len</span>(nums)<br> l = r = <span class="hljs-number">0</span><br> <span class="hljs-keyword">while</span> r < n:<br> <span class="hljs-keyword">if</span> nums[r] != <span class="hljs-number">0</span>:<br> nums[l],nums[r] = nums[r], nums[l] <span class="hljs-comment"># 快速实现两个元素的交换</span><br> l += <span class="hljs-number">1</span><br> r += <span class="hljs-number">1</span><br> <br></code></pre></td></tr></table></figure><h3 id="2-盛最多水的容器"><a href="#2-盛最多水的容器" class="headerlink" title="2.盛最多水的容器"></a>2.盛最多水的容器</h3><ul><li><p>描述:给定一个长度为 <code>n</code> 的整数数组 <code>height</code> 。有 <code>n</code> 条垂线,第 <code>i</code> 条线的两个端点是 <code>(i, 0)</code> 和 <code>(i, height[i])</code> 。</p><p>找出其中的两条线,使得它们与 <code>x</code> 轴共同构成的容器可以容纳最多的水。</p><p>返回容器可以储存的最大水量。</p><p><strong>说明:</strong>你不能倾斜容器。</p></li></ul><h4 id="思路一:-1"><a href="#思路一:-1" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>贪心算法,左右指针分别从两端开始往中间靠,此时中间的任意的选择都是有可能。比较两个指针指向的数,选择高度较小的往中间走一步。</li><li>==证明==:从第一步开始假设,当前两个指针l, r直向左右两端,值分别是x, y,假设x<=y,距离为t,那么此时的结果就是min(x, y)*t = xt。假设左指针不动,此时右指针可以向左移动,不管怎么移动,其结果都是小于xt的,因为此时距离减少了,而min(x, y(new)) <= min(x, y) = x。因此所有以左指针为一端的结果都可以直接舍弃掉了,于是可以直接选择将左指针向右移动一步即可。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">maxArea</span>(<span class="hljs-params">self, height: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-built_in">int</span>:<br> ans = <span class="hljs-number">0</span><br> n = <span class="hljs-built_in">len</span>(height)<br> l, r= <span class="hljs-number">0</span>, n-<span class="hljs-number">1</span><br> <span class="hljs-keyword">while</span> l < r:<br> width = r-l<br> <span class="hljs-keyword">if</span> height[l] < height[r]:<br> ans = <span class="hljs-built_in">max</span>(ans, width*height[l])<br> l += <span class="hljs-number">1</span><br> <span class="hljs-keyword">else</span>:<br> ans = <span class="hljs-built_in">max</span>(ans, width*height[r])<br> r -= <span class="hljs-number">1</span><br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h3 id="3-三数之和:"><a href="#3-三数之和:" class="headerlink" title="3.三数之和:"></a>3.三数之和:</h3><ul><li><p>描述:给你一个整数数组 <code>nums</code> ,判断是否存在三元组 <code>[nums[i], nums[j], nums[k]]</code> 满足 <code>i != j</code>、<code>i != k</code> 且 <code>j != k</code> ,同时还满足 <code>nums[i] + nums[j] + nums[k] == 0</code> 。请你返回所有和为 <code>0</code> 且不重复的三元组。</p><p><strong>注意:</strong>答案中不可以包含重复的三元组。</p></li></ul><h4 id="思路一:-2"><a href="#思路一:-2" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li><p>关键在于<strong>降低时间复杂度</strong>和<strong>重复的剪枝</strong>,暴力的做法就是三层循环O[N^3]。首先对数组进行排序,方便计算,在第二层和第三层循环使用双指针,不断向中间移动来寻找对应的target,这部分的时间复杂度就从O[N^2]降低到O[N]了。然后是在第一二层循环的时候都进行一下判重,找到并使用多个连续的重复数字的最后那一个。</p></li><li><p>代码:</p></li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">threeSum</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]]:<br> nums.sort()<br> n = <span class="hljs-built_in">len</span>(nums)<br> ans = <span class="hljs-built_in">list</span>()<br> <br> <span class="hljs-keyword">for</span> a <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n-<span class="hljs-number">2</span>):<br> <span class="hljs-keyword">if</span> a > <span class="hljs-number">0</span> <span class="hljs-keyword">and</span> nums[a] == nums[a-<span class="hljs-number">1</span>]: <span class="hljs-comment"># 跳过重复的数字</span><br> <span class="hljs-keyword">continue</span><br> c = n - <span class="hljs-number">1</span><br> target = -nums[a]<br> <span class="hljs-keyword">for</span> b <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(a+<span class="hljs-number">1</span>, n-<span class="hljs-number">1</span>):<br> <span class="hljs-keyword">if</span> b > a + <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> nums[b] == nums[b-<span class="hljs-number">1</span>]: <span class="hljs-comment">#跳重</span><br> <span class="hljs-keyword">continue</span><br> <span class="hljs-keyword">while</span> b < c <span class="hljs-keyword">and</span> nums[b] + nums[c] > target: <span class="hljs-comment">#c的重复没有影响,当找到时会直接跳出</span><br> c -= <span class="hljs-number">1</span><br> <span class="hljs-keyword">if</span> b == c:<br> <span class="hljs-keyword">break</span><br> <span class="hljs-keyword">if</span> nums[b] + nums[c] == target:<br> ans.append([nums[a], nums[b], nums[c]])<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h3 id="4-接雨水:"><a href="#4-接雨水:" class="headerlink" title="4.接雨水:"></a>4.接雨水:</h3><ul><li>描述:给定 <code>n</code> 个非负整数表示每个宽度为 <code>1</code> 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。</li></ul><h4 id="思路一:-3"><a href="#思路一:-3" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>动态规划,提前维护数组LeftMax和RightMax,对于每一个位置来说,它能接收的与水量为左右两边对应的最大值取较小值然后减去当前位置的高度。相当于求每个位置上的雨水高度然后累加</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">trap</span>(<span class="hljs-params">self, height: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-built_in">int</span>:<br> n = <span class="hljs-built_in">len</span>(height)<br> ans = <span class="hljs-number">0</span><br><br> leftMax = [height[<span class="hljs-number">0</span>]] + [<span class="hljs-number">0</span>]*(n - <span class="hljs-number">1</span>) <span class="hljs-comment"># 数组连接来实现初始化</span><br> rightMax = [<span class="hljs-number">0</span>]*(n - <span class="hljs-number">1</span>) + [height[n - <span class="hljs-number">1</span>]]<br><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, n):<br> leftMax[i] = <span class="hljs-built_in">max</span>(leftMax[i-<span class="hljs-number">1</span>], height[i]) <span class="hljs-comment"># 从左往右更新</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n-<span class="hljs-number">2</span>, <span class="hljs-number">0</span>, -<span class="hljs-number">1</span>):<br> rightMax[i] = <span class="hljs-built_in">max</span>(rightMax[i+<span class="hljs-number">1</span>], height[i]) <span class="hljs-comment"># 从右往左更新</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-number">1</span>, n-<span class="hljs-number">1</span>):<br> ans += <span class="hljs-built_in">min</span>(leftMax[i], rightMax[i]) - height[i]<br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h4 id="思路二:-1"><a href="#思路二:-1" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>单调栈,维护一个递减的序列,当遇到一个大于当前栈顶的值时,就出栈一个为top,然后将此时的栈顶和当前的值作为两端,top作为计算的位置。是以矩阵形式累加答案的,通过遍历一边数组就合计了所有的计算,很巧妙。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">trap</span>(<span class="hljs-params">self, height: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-built_in">int</span>:<br> n = <span class="hljs-built_in">len</span>(height)<br> ans = <span class="hljs-number">0</span><br> stack = <span class="hljs-built_in">list</span>() <span class="hljs-comment"># 初始化栈</span><br><br> <span class="hljs-keyword">for</span> i, h <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(height):<br> <span class="hljs-keyword">while</span> stack <span class="hljs-keyword">and</span> h > height[stack[-<span class="hljs-number">1</span>]]: <span class="hljs-comment"># 只要栈非空或者出现了大于栈顶的数就不断执行</span><br> top = stack.pop()<br> <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> stack: <span class="hljs-comment">#一旦栈空了就退出</span><br> <span class="hljs-keyword">break</span><br> left = stack[-<span class="hljs-number">1</span>]<br> curWidth = i - left - <span class="hljs-number">1</span> <span class="hljs-comment"># 对应的宽度</span><br> curHeight = <span class="hljs-built_in">min</span>(height[left], height[i]) - height[top] <span class="hljs-comment">#对应的高度</span><br> ans += curHeight*curWidth<br> stack.append(i) <span class="hljs-comment"># 无一例外地添加到栈中</span><br> <span class="hljs-keyword">return</span> ans<br></code></pre></td></tr></table></figure><h4 id="思路三"><a href="#思路三" class="headerlink" title="思路三:"></a>思路三:</h4><ul><li>双指针,是对思路一的优化,对于每个点,只需要知道它左右的最大值分别是多少即可,不需要把所有的值都计算出来,而这个需要的值可以在双指针移动的过程中得到。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">trap</span>(<span class="hljs-params">self, height: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-built_in">int</span>:<br> n = <span class="hljs-built_in">len</span>(height)<br> ans = <span class="hljs-number">0</span><br> l, r = <span class="hljs-number">0</span>, n - <span class="hljs-number">1</span><br> leftMax = height[<span class="hljs-number">0</span>]<br> rightMax = height[n - <span class="hljs-number">1</span>]<br> <span class="hljs-keyword">while</span> l < r:<br> leftMax = <span class="hljs-built_in">max</span>(leftMax, height[l])<br> rightMax = <span class="hljs-built_in">max</span>(rightMax, height[r]) <span class="hljs-comment"># 及时更新对应的两个左右最大值</span><br> <span class="hljs-keyword">if</span> height[l] < height[r]: <span class="hljs-comment"># 相当于leftMax < rightMax, 对于l来说,左右两端的最大值的较小值就是leftMax</span><br> ans += leftMax - height[l] <br> l += <span class="hljs-number">1</span><br> <span class="hljs-keyword">else</span>:<br> ans += rightMax - height[r]<br> r -= <span class="hljs-number">1</span><br> <br> <span class="hljs-keyword">return</span> ans<br><br></code></pre></td></tr></table></figure><h3 id="小节:"><a href="#小节:" class="headerlink" title="小节:"></a>小节:</h3><ul><li>双指针对于数组的操作更加灵活,比如移动零,可以对元素进行划分,也类似快速排序里的双指针</li><li>双指针+排序可以降低时间复杂度,把O[N^2]降为O[N]</li><li>双指针也可以是两个数组的简化,比如接雨水,作为重要的临时变量,按具体情况进行移动</li><li><strong>更多在于元素之间的关系的体现,通过移动来实现一种筛选</strong></li></ul>]]></content>
<categories>
<category>力扣</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>力扣100题---哈希</title>
<link href="/2024/08/03/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E5%93%88%E5%B8%8C/"/>
<url>/2024/08/03/%E5%8A%9B%E6%89%A3100%E9%A2%98/%E5%8A%9B%E6%89%A3100%E9%A2%98-%E5%93%88%E5%B8%8C/</url>
<content type="html"><![CDATA[<h3 id="1-两数之和"><a href="#1-两数之和" class="headerlink" title="1.两数之和"></a>1.两数之和</h3><ul><li><p>描述:给定一个整数数组 <code>nums</code> 和一个整数目标值 <code>target</code>,请你在该数组中找出 <strong>和为目标值</strong> <em><code>target</code></em> 的那 <strong>两个</strong> 整数,并返回它们的数组下标。</p><p>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</p><p>你可以按任意顺序返回答案</p></li></ul><h4 id="思路一:"><a href="#思路一:" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>暴力模拟,两个变量从前往后遍历,避免重复和自己和自己配对</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">twoSum</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>], target: <span class="hljs-built_in">int</span></span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]:<br> n = <span class="hljs-built_in">len</span>(nums) <span class="hljs-comment"># 获取数组长度</span><br> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(n):<br> <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(i+<span class="hljs-number">1</span>, n):<br> <span class="hljs-keyword">if</span>(nums[i] + nums[j] == target):<br> <span class="hljs-keyword">return</span> [i,j]<br> <br> <span class="hljs-keyword">return</span> []<br><br><br></code></pre></td></tr></table></figure><h4 id="思路二:"><a href="#思路二:" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>使用HASH表记录之前出现过的数字以及它的下标,那么只需要遍历数组一次,即O(N)的复杂度就可以找到对应的答案了</li><li>代码</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">twoSum</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>], target: <span class="hljs-built_in">int</span></span>) -> <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]:<br> hashtable = <span class="hljs-built_in">dict</span>() <span class="hljs-comment"># 用字典初始化哈希表</span><br> <span class="hljs-keyword">for</span> i, num <span class="hljs-keyword">in</span> <span class="hljs-built_in">enumerate</span>(nums): <span class="hljs-comment"># enumerate来获取nums的元素</span><br> <span class="hljs-keyword">if</span> target - num <span class="hljs-keyword">in</span> hashtable: <span class="hljs-comment"># in来判断是否存在于哈希表</span><br> <span class="hljs-keyword">return</span>[hashtable[target - num], i]<br> hashtable[num] = i <span class="hljs-comment"># 存进哈希表</span><br> <span class="hljs-keyword">return</span> []<br></code></pre></td></tr></table></figure><h3 id="2-字母异位词分组"><a href="#2-字母异位词分组" class="headerlink" title="2.字母异位词分组"></a>2.字母异位词分组</h3><ul><li><p>描述:给你一个字符串数组,请你将 <strong>字母异位词</strong> 组合在一起。可以按任意顺序返回结果列表。</p><p><strong>字母异位词</strong> 是由重新排列源单词的所有字母得到的一个新单词。</p></li></ul><h4 id="思路一:-1"><a href="#思路一:-1" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>将每个单词的排序后的词作为哈希表的key,依次加入到对应的哈希值里,哈希表的value采取default的list,最终以list的形式返回哈希表的所有值</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">groupAnagrams</span>(<span class="hljs-params">self, strs: <span class="hljs-type">List</span>[<span class="hljs-built_in">str</span>]</span>) -> <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">str</span>]]:<br> mp = collections.defaultdict(<span class="hljs-built_in">list</span>) <span class="hljs-comment"># 初始化有默认值的哈希表</span><br> <span class="hljs-keyword">for</span> st <span class="hljs-keyword">in</span> strs:<br> key = <span class="hljs-string">""</span>.join(<span class="hljs-built_in">sorted</span>(st)) <span class="hljs-comment"># 对st进行排序后再重新连接成一个新的字符串</span><br> mp[key].append(st) <span class="hljs-comment"># append加入对应的key的哈希值</span><br> <span class="hljs-keyword">return</span> <span class="hljs-built_in">list</span>(mp.values()) <span class="hljs-comment">#返回list形式的所有哈希值</span><br></code></pre></td></tr></table></figure><h4 id="思路二:-1"><a href="#思路二:-1" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>把每个单词里26个字母按顺序出现的次数作为哈希表的key</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">groupAnagrams</span>(<span class="hljs-params">self, strs: <span class="hljs-type">List</span>[<span class="hljs-built_in">str</span>]</span>) -> <span class="hljs-type">List</span>[<span class="hljs-type">List</span>[<span class="hljs-built_in">str</span>]]:<br> mp = collections.defaultdict(<span class="hljs-built_in">list</span>) <span class="hljs-comment"># 初始化哈希表</span><br> <span class="hljs-keyword">for</span> st <span class="hljs-keyword">in</span> strs:<br> count = [<span class="hljs-number">0</span>] * <span class="hljs-number">26</span> <span class="hljs-comment"># 初始化字母出现次数</span><br> <span class="hljs-keyword">for</span> ch <span class="hljs-keyword">in</span> st:<br> count[<span class="hljs-built_in">ord</span>(ch) - <span class="hljs-built_in">ord</span>(<span class="hljs-string">"a"</span>)] += <span class="hljs-number">1</span> <span class="hljs-comment"># ord获取字母的ASCII码</span><br> mp[<span class="hljs-built_in">tuple</span>(count)].append(st) <span class="hljs-comment"># list不能直接作为键,先转化为tuple类型</span><br> <br> <span class="hljs-keyword">return</span> <span class="hljs-built_in">list</span>(mp.values())<br></code></pre></td></tr></table></figure><h3 id="3-最长连续序列"><a href="#3-最长连续序列" class="headerlink" title="3.最长连续序列"></a>3.最长连续序列</h3><ul><li><p>描述:给定一个未排序的整数数组 <code>nums</code> ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。</p><p>请你设计并实现时间复杂度为 <code>O(n)</code> 的算法解决此问题。</p></li></ul><h4 id="思路一:-2"><a href="#思路一:-2" class="headerlink" title="思路一:"></a>思路一:</h4><ul><li>先对nums去重,存储在set里,本身就是个哈希表,查找速度为O(1)。为了避免重复遍历连续数组,在遍历前先判断当前数字num的num-1是否存在,使得每次遍历都是从连续数据的第一个数开始的。最终整体的时间复杂度为O(N)</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">longestConsecutive</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-built_in">int</span>:<br> longest = <span class="hljs-number">0</span><br> num_set = <span class="hljs-built_in">set</span>(nums) <span class="hljs-comment"># set去重查找迅速</span><br><br> <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> num_set:<br> <span class="hljs-keyword">if</span> num - <span class="hljs-number">1</span> <span class="hljs-keyword">not</span> <span class="hljs-keyword">in</span> num_set: <span class="hljs-comment"># 判断是否是连续数组的第一个</span><br> <span class="hljs-built_in">len</span> = <span class="hljs-number">1</span><br> cur_num = num<br><br> <span class="hljs-keyword">while</span> cur_num + <span class="hljs-number">1</span> <span class="hljs-keyword">in</span> num_set:<br> <span class="hljs-built_in">len</span> += <span class="hljs-number">1</span><br> cur_num += <span class="hljs-number">1</span><br> <br> longest = <span class="hljs-built_in">max</span>(longest, <span class="hljs-built_in">len</span>)<br> <br> <span class="hljs-keyword">return</span> longest<br></code></pre></td></tr></table></figure><h4 id="思路二:-2"><a href="#思路二:-2" class="headerlink" title="思路二:"></a>思路二:</h4><ul><li>利用并查集,把连续数字作为并查集的定义,不断进行合并,那么最终长度最大的并查集就是最长的连续数组。时间复杂度可以看作是O(N)。</li><li>代码:</li></ul><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs python"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span>:<br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">longestConsecutive</span>(<span class="hljs-params">self, nums: <span class="hljs-type">List</span>[<span class="hljs-built_in">int</span>]</span>) -> <span class="hljs-built_in">int</span>:<br> nums = <span class="hljs-built_in">set</span>(nums) <span class="hljs-comment">#去重</span><br> ans = <span class="hljs-number">0</span><br><br> fa = {num: num <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> nums}<br> size = {num: <span class="hljs-number">1</span> <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> nums} <span class="hljs-comment"># 初始化 </span><br><br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">find</span>(<span class="hljs-params">x</span>):<br> <span class="hljs-keyword">if</span> fa[x] != x:<br> fa[x] = find(fa[x])<br> <span class="hljs-keyword">return</span> fa[x]<br> <br> <span class="hljs-keyword">def</span> <span class="hljs-title function_">merge</span>(<span class="hljs-params">f, to</span>): <span class="hljs-comment">#并查集模板</span><br> f = find(f)<br> to = find(to)<br> <span class="hljs-keyword">if</span> f != to:<br> fa[f] = to<br> size[to] += size[f]<br> <br> <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> nums:<br> <span class="hljs-keyword">if</span> num + <span class="hljs-number">1</span> <span class="hljs-keyword">in</span> nums:<br> merge(num, num + <span class="hljs-number">1</span>)<br> <br> <span class="hljs-keyword">if</span> size: <span class="hljs-comment"># 防止这是一个空数组</span><br> ans = <span class="hljs-built_in">max</span>(size.values())<br> <span class="hljs-keyword">return</span> ans<br> <br></code></pre></td></tr></table></figure><h3 id="小节:"><a href="#小节:" class="headerlink" title="小节:"></a>小节:</h3><ul><li>哈希表的主要作用是<strong>降低查找的时间复杂度</strong>,从而降低整体的时间复杂度</li><li>哈希表的<strong>初始化</strong><ul><li>dict()</li><li>collections.defaultdict()—需要默认值</li><li>set()—初始化为set数据结构,去重的同时查找速度也很快</li></ul></li><li>哈希表的<strong>键必须是不可变的</strong>,包括整数(int)、浮点数(float)、字符串(str)、元组(tuple)。列表(list)是可变的对象,需要转化为tuple再作为哈希表的键</li></ul>]]></content>
<categories>
<category>力扣</category>
</categories>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>小游戏浅浅分析</title>
<link href="/2024/07/21/game/%E5%B0%8F%E6%B8%B8%E6%88%8F%E6%B5%85%E6%B5%85%E5%88%86%E6%9E%90/"/>
<url>/2024/07/21/game/%E5%B0%8F%E6%B8%B8%E6%88%8F%E6%B5%85%E6%B5%85%E5%88%86%E6%9E%90/</url>
<content type="html"><![CDATA[<h2 id="黄金矿工改编版分析"><a href="#黄金矿工改编版分析" class="headerlink" title="黄金矿工改编版分析"></a>黄金矿工改编版分析</h2><h5 id="URL"><a href="#URL" class="headerlink" title="URL:"></a>URL:</h5><h5 id="https-www-4399-com-flash-3869-htm-search3-0d18"><a href="#https-www-4399-com-flash-3869-htm-search3-0d18" class="headerlink" title="https://www.4399.com/flash/3869.htm#search3-0d18"></a><a href="https://www.4399.com/flash/3869.htm#search3-0d18">https://www.4399.com/flash/3869.htm#search3-0d18</a></h5><h5 id="Analysis"><a href="#Analysis" class="headerlink" title="Analysis:"></a>Analysis:</h5><p>玩了三局改编版黄金矿工</p><p>可以很明显地感受到心跳变快手心出汗,游戏确实难以抵抗</p><p>玩的时候就在简单分析了,尝试写点:</p><ul><li><p><strong>一个是音效,和动作结合,简单有效</strong></p></li><li><p><strong>一个是地图点亮,难度平滑增加,刺激挑战欲,我基本最多点亮一半。想到羊了个羊,后期的地狱难度更能留住用户。每一级有几个备选场景,不会容易枯燥,也不会容易习惯。</strong></p></li><li><p><strong>一个是商品售卖,钓的除了过关分数还有钱,用钱买商品。除了炸弹还有怪物分数加倍道具,幸运草,加时器等,功能齐全</strong></p></li><li><p>除了固定的金矿和石头,还有4个小物件,面积小不好钓,但集齐分数会很多,后期的有些关卡还有会飞的怪物,礼物(内含分数或钱或强力,不确定),以及炸弹桶,增加刺激性</p></li><li><p>每关有限定的过关分数,多余分数会累积到下一关,但不会超过下一关的过关分数,增加了一点难度</p></li></ul><h5 id="Summary"><a href="#Summary" class="headerlink" title="Summary:"></a>Summary:</h5><p>语言风格都是英文,应该是外国人开发的,感觉比经典版本更加丰富,可玩性也不错,改编地很棒。小小的游戏也有不少说道,用到了不少<strong>用户心理的把握</strong>,有意思</p><p></p>]]></content>
<categories>
<category>游戏开发</category>
</categories>
<tags>
<tag>game</tag>
</tags>
</entry>
<entry>
<title>蓝桥杯国赛备赛总结</title>
<link href="/2024/05/31/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B%E6%80%BB%E7%BB%93/"/>
<url>/2024/05/31/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B%E6%80%BB%E7%BB%93/</url>
<content type="html"><![CDATA[<h2 id=""><a href="#" class="headerlink" title=""></a></h2><h2 id="-1"><a href="#-1" class="headerlink" title=""></a></h2><h2 id="蓝桥杯国赛比赛注意点"><a href="#蓝桥杯国赛比赛注意点" class="headerlink" title="蓝桥杯国赛比赛注意点"></a>蓝桥杯国赛比赛注意点</h2><h3 id="1-知识点总结:"><a href="#1-知识点总结:" class="headerlink" title="1.知识点总结:"></a>1.知识点总结:</h3><h4 id="2022年国A:"><a href="#2022年国A:" class="headerlink" title="2022年国A:"></a>2022年国A:</h4><ul><li>前两道填空题涉及错排和康托展开比较不常用的算法,没有想出来可以跳过,或者可以尝试寻找规律去做。</li><li>C题模拟题,细心就可以做出来</li><li>D题模拟可以拿大部分分数,正解是线段树+二分,也是比较基础的使用,可以尝试去想正解</li><li>E题分类情况比较复杂,通过随机函数来暴力求解可以得到部分分数</li><li>F题图的存储,Floyed+二分,可以大胆尝试去做,基本算法的组合</li><li>G题数学题,考察线性筛,也有暴力的可能,先分析出题眼是什么,到底要解决什么问题</li><li>H题简单暴力题,可以过70%的点</li><li>I题暴力模拟+二分,分类情况比较多,预先的思路需要很清晰,根据时间情况,可以尝试获得部分数</li></ul><h4 id="2023年国A:"><a href="#2023年国A:" class="headerlink" title="2023年国A:"></a>2023年国A:</h4><ul><li>前两道填空题涉及很偏门的算法,属于学了学不会的,研究一下不会的话跳过即可</li><li>C题暴力模拟题,细心即可</li><li>D题规律题,总结规律,要对特殊情况多加测试</li><li>E题二分+二分,是可以做出来的,思路可以大胆一点,分析暴力复杂度高的原因进而去解决</li><li>F题图的存储,二分类问题,去分析问题可能的情况,思路并不难。主要是熟练点和边的存储</li><li>G题dfs+剪枝,dfs的就是考虑退出条件,分类往下,恢复现场,返回退出这几点,思路清晰很重要</li><li>H题字符串暴力题,要熟悉字符串的常见处理,结合map来使用</li><li>I题lca暴力可以过65%,背模板还是很事半功倍的</li></ul><h4 id="2023年国B:"><a href="#2023年国B:" class="headerlink" title="2023年国B:"></a>2023年国B:</h4><ul><li>前两道填空题暂且跳过</li><li>C题分类模拟,比较简单,注意细节即可</li><li>D题双指针,多多测试特殊情况,并不复杂</li><li>E题暴力题或者利用STL降低复杂度,考察对于set, map的使用</li><li>F题图的存储,tarjan连通块,不会跳过</li><li>G题BFS+分层图,在BFS基础上增加一个判定维度,可以尝试去做一下</li><li>H题二分,通过二分找到两个端点即可求解</li><li>I题看不懂跳过</li></ul><h5 id="分数分布:5-5-10-10-15-15-20-20-25-25-150分"><a href="#分数分布:5-5-10-10-15-15-20-20-25-25-150分" class="headerlink" title="分数分布:5+5+10+10+15+15+20+20+25+25=150分"></a>分数分布:5+5+10+10+15+15+20+20+25+25=150分</h5><h4 id="题型总结:"><a href="#题型总结:" class="headerlink" title="题型总结:"></a>题型总结:</h4><ul><li>前两道填空题考察的算法一半会就是会,不会就是不会,研究一下,做不出来可以果断放弃</li><li>C,D,E题相对比较简单,C,D反复测试去拿全部分数,E题大胆尝试正解,一定要多加测试,注意特殊情况</li><li>F题一般是<strong>图的存储</strong>,仔细分析问题的情况,完全可以去大胆尝试的</li><li>G,H,I题可能涉及<strong>树,数学题,字符串处理,dfs/bfs,二分暴力求解</strong>,都是<strong>基本算法的结合或者暴力</strong>可以获得大部分分数,每一题都要仔细过一遍,尽可能地得分。</li></ul><h3 id="2-做题策略:"><a href="#2-做题策略:" class="headerlink" title="2.做题策略:"></a>2.做题策略:</h3><ul><li><strong>两道填空题</strong>不要用过多的时间,不会的话果断放弃</li><li><strong>前三道算法题</strong>尽可能去想正解,反复多加测试,完全可以多放一些时间,稳稳地去做,不必着急</li><li><strong>后四道题或者加上最后一道题</strong>,可以去拿部分分甚至全部的分数,很多可以暴力求解,多想几组测试数据,稳中求胜</li></ul><h3 id="3-时间安排:"><a href="#3-时间安排:" class="headerlink" title="3.时间安排:"></a>3.时间安排:</h3><ul><li><p>开始先敲好代码框架(包括signed),运行没有问题,复制多个,命名A-I,以及可以有一个test程序方便临时测试</p></li><li><p><strong>注意在一道题目上不要停留过长的时间</strong>,不要超过30-40分钟,可以先放一放,做后面的题,之后可以再回过头来看,可能会有新思路</p></li><li><p>最后一定要<strong>留40分钟以上</strong>的时间来检查所有题目,把提交的内容再拿回来测试,或是可以暴力模拟拿分的题目再想想有没有更好的办法。<strong>最后几分钟</strong>再看一下提交的内容有没有问题</p></li></ul><h3 id="-2"><a href="#-2" class="headerlink" title=""></a></h3>]]></content>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>蓝桥杯备赛-复习和模拟赛</title>
<link href="/2024/05/30/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%A4%87%E8%B5%9B-%E5%A4%8D%E4%B9%A0%E5%92%8C%E6%A8%A1%E6%8B%9F%E8%B5%9B/"/>
<url>/2024/05/30/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%A4%87%E8%B5%9B-%E5%A4%8D%E4%B9%A0%E5%92%8C%E6%A8%A1%E6%8B%9F%E8%B5%9B/</url>
<content type="html"><![CDATA[<h2 id="复习"><a href="#复习" class="headerlink" title="复习"></a>复习</h2><h4 id="1-选素数-线性筛"><a href="#1-选素数-线性筛" class="headerlink" title="1.选素数:线性筛"></a>1.选素数:线性筛</h4><ul><li>思路:根据题目规律分析出求f(n) = n-pmax+1,<strong>n不为素数</strong>,接下来就是利用线性筛来求每个数的pmax了。模板还是比较好记的。</li><li>总结:代码长度不长,主要要根据<strong>规律分析</strong>出如何求解的x以及知道<strong>利用线性筛求数的最大质因子</strong>。</li></ul><h4 id="2-单源最短路:dijkstra"><a href="#2-单源最短路:dijkstra" class="headerlink" title="2.单源最短路:dijkstra"></a>2.单源最短路:dijkstra</h4><ul><li>思路:主要采用<strong>链式前向星</strong>和<strong>优先队列</strong>来实现单源最短路的更新,模板的写法要非常熟悉。</li></ul><h4 id="3-字符迁移:差分"><a href="#3-字符迁移:差分" class="headerlink" title="3.字符迁移:差分"></a>3.字符迁移:差分</h4><ul><li>思路:连续一段区间加一个数就是差分的特点,cha[l]+=k,cha[r+1]-=k,然后前差分数组的前缀和就是最终原数组。写一个示例数组就能很清晰地理清两者的关系了。</li><li><strong>注意:</strong>%不要在差分求解的过程中进行,会打乱数组。在原数组求解出来之后在对应进行%运算。</li></ul><h4 id="强者挑战赛11:"><a href="#强者挑战赛11:" class="headerlink" title="强者挑战赛11:"></a>强者挑战赛11:</h4><h4 id="A玩偶购买:"><a href="#A玩偶购买:" class="headerlink" title="A玩偶购买:"></a>A玩偶购买:</h4><ul><li>分类讨论,一些细节要多多注意,通过几次调试过了。但是正式比赛的时候一定要细心细心再细心,多多输出中间条件来测试。</li></ul><h4 id="B数学魔法家:"><a href="#B数学魔法家:" class="headerlink" title="B数学魔法家:"></a>B数学魔法家:</h4><ul><li>两种情况,主要是前导零的情况要进行特殊处理,多加测试,做出来了。</li></ul><h4 id="C矿石样本分析:"><a href="#C矿石样本分析:" class="headerlink" title="C矿石样本分析:"></a>C矿石样本分析:</h4><ul><li>map存储来实现快速查找,注意两个矿石的值不能相同,题目的限定条件最好还是写下来,不容易忘记。修改了一次最终通过了。</li></ul><h4 id="D拔苗助长:"><a href="#D拔苗助长:" class="headerlink" title="D拔苗助长:"></a>D拔苗助长:</h4><ul><li>考察完全平方数的唯一分解定律,它分解为多个质数相乘,那么质数的系数一定是偶数。选任意两个数相乘为完全平方数,那么它们对应的质因子的和应该为偶数,当出现在一个数内出现了奇数次x的质数时,需要进行操作,它们要么全变成偶数(x次),要么把剩余的全变成奇数(n-x),两者取较小值。</li><li>还是有点晕晕,结合具体的例子来看会清晰很多。评论区翻到的代码太厉害了。尤其是分解质因子这里很巧妙!</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs c++">unordered_map<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> mp;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">2</span>;j*j<=a[i]; j++){<br><span class="hljs-type">int</span> cnt = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">while</span>(a[i]%j==<span class="hljs-number">0</span>){<br>a[i]/=j;<br>cnt++;<br>}<br><span class="hljs-keyword">if</span>(cnt%<span class="hljs-number">2</span>==<span class="hljs-number">1</span>){<br>mp[j]++;<br>}<br>}<br><span class="hljs-keyword">if</span>(a[i]!=<span class="hljs-number">1</span>){<br>mp[a[i]]++;<br>}<br>}<br></code></pre></td></tr></table></figure><ul><li>另外,线性筛还可以用来求最小质因子</li></ul>]]></content>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>2023年蓝桥杯国B</title>
<link href="/2024/05/27/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/2023%E5%B9%B4%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BDB/"/>
<url>/2024/05/27/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/2023%E5%B9%B4%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BDB/</url>
<content type="html"><![CDATA[<h2 id="2023年蓝桥杯国赛B组"><a href="#2023年蓝桥杯国赛B组" class="headerlink" title="2023年蓝桥杯国赛B组"></a>2023年蓝桥杯国赛B组</h2><h4 id="C班级活动:"><a href="#C班级活动:" class="headerlink" title="C班级活动:"></a>C班级活动:</h4><ul><li>分类讨论即可,题目并不难,但是卡在了数组越界,N是数组的大小,然后又从1遍历到N就会出问题,经验+1,要注意避免这种情况。</li></ul><h4 id="D合并数列:"><a href="#D合并数列:" class="headerlink" title="D合并数列:"></a>D合并数列:</h4><ul><li>模拟题,把两种不等的情况合并起来,最后调试做出来了。还是要多多考虑特殊情况,比如必须要合并所有的情况来测试,在比赛过程中要多多考虑最特殊的情况,多加测试才更能保证得分。</li></ul><h4 id="E数三角:"><a href="#E数三角:" class="headerlink" title="E数三角:"></a>E数三角:</h4><ul><li>暴力模拟:可以过75%,刚开始陷入了三角形共线的判断,实则可以换一个思路,用两边之和大于第三边去判断,简化步骤。</li><li>不要一直局限在一个做法里,可以多多思考有没有其他方式解决。是可以拿到部分分的。</li><li>期间,用了求共线的方式,看似可行,但是分支情况太多,导致实际上一个点也过不了,要多方验证,有很严谨的推导过程。最好一开始就想好代码怎么实现,但也不必害怕中途改方式,说不定会有更加简单可实现的。</li><li>正解:使用枚举+STL,灵活使用set(不重复,快速找元素是否存在),map(计数),还有把复杂计算均摊在for循环里解决,很巧妙的做法。</li></ul><h4 id="F删边问题:0"><a href="#F删边问题:0" class="headerlink" title="F删边问题:0"></a>F删边问题:0</h4><h4 id="GAB路线:"><a href="#GAB路线:" class="headerlink" title="GAB路线:"></a>GAB路线:</h4><ul><li>思路:BFS+分层图,对于每个st,增加一个第几个的维度,分成等于k和小于k两种情况去执行下一步的扩展。通过这道题目,熟悉了BFS模板。</li></ul><h4 id="H抓娃娃:"><a href="#H抓娃娃:" class="headerlink" title="H抓娃娃:"></a>H抓娃娃:</h4><ul><li>思路:先简化问题,只要重点在区间内即可。然后二分找到左右最合适的端点,求出这两个端点内的数目就是答案。</li></ul><h4 id="I拼数字:0"><a href="#I拼数字:0" class="headerlink" title="I拼数字:0"></a>I拼数字:0</h4>]]></content>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>重做2023年国A</title>
<link href="/2024/05/17/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E9%87%8D%E5%81%9A2023%E5%B9%B4%E5%9B%BDA/"/>
<url>/2024/05/17/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E9%87%8D%E5%81%9A2023%E5%B9%B4%E5%9B%BDA/</url>
<content type="html"><![CDATA[<h2 id="重做2023年国A"><a href="#重做2023年国A" class="headerlink" title="重做2023年国A"></a>重做2023年国A</h2><h4 id="C切割:"><a href="#C切割:" class="headerlink" title="C切割:"></a>C切割:</h4><ul><li>思路:简单的模拟题,根据题意来模拟即可,可以多加测试来降低风险</li></ul><h4 id="DXYZ"><a href="#DXYZ" class="headerlink" title="DXYZ:"></a>DXYZ:</h4><ul><li>思路:找规律题目,总结公式,从样例出发,耐心一点完全可以做出来,很棒!</li></ul><h4 id="E第K小的和:"><a href="#E第K小的和:" class="headerlink" title="E第K小的和:"></a>E第K小的和:</h4><ul><li>思路:双重二分,调试了一会儿边界最终做出来了!二分条件的基本原则还是要坚持(<strong>等号在哪,哪里没有加减1。然后就是考虑找最左还是最右,没有结果的时候又要返回什么</strong>),然后如果出错就debug输出也会比较容易找到问题所在,细心一点即可。最后N忘记设大一点导致一个点没过,经验+1。</li></ul><h4 id="F相连的边:"><a href="#F相连的边:" class="headerlink" title="F相连的边:"></a>F相连的边:</h4><ul><li>思路:图的存储和遍历。</li><li>三条相连的边的和最大,先分析有两种情况,一是三条边有一共同端点,二是三条边首位相连。对于一,遍历所有点,所连的边按照边长倒叙排序,取前3个(>=3)。对于二,遍历所有边,对于两个端点分别取所连的边的最长,不能是当前边,需要增加一个id变量来标记每一条边。使用了vector<edge> node这一类型。</li><li>主要在于分类分析,对一种情况的边界情况要考虑清楚,是可以做出来的。</li></ul><h4 id="G01游戏:"><a href="#G01游戏:" class="headerlink" title="G01游戏:"></a>G01游戏:</h4><ul><li>思路:01图dfs求解。</li><li>有三个限定条件:一是水平或垂直,不能出现连续3个0或1,二是每行每列的0,1个数都要想到,三是每行每列各不相同(n比较小,可以用状压数组记录)。针对限定条件及时进行剪枝。从左往右,从上到下遍历,最终进行验证。dfs有0和1两个分支,注意要恢复现场。</li><li>出现问题去输出再加上逻辑分析基本就可以判定解决问题,可以做出来,很棒!</li></ul><h4 id="H子串:"><a href="#H子串:" class="headerlink" title="H子串:"></a>H子串:</h4><ul><li>思路:字符串hash</li><li>暴力枚举所有子串,先遍历len,再遍历起始位置,s.substr(i, len)来获取子串,可以过25%,不错👍</li></ul><h4 id="I树上的路径:"><a href="#I树上的路径:" class="headerlink" title="I树上的路径:"></a>I树上的路径:</h4><ul><li>树上距离枚举</li><li>利用lca来求两点之间的距离,可以过65%,利用lca的模板求树上两点距离已经比较熟练了</li></ul><h4 id="总结:"><a href="#总结:" class="headerlink" title="总结:"></a>总结:</h4><p>1.题目分布:</p><ul><li><strong>两道填空题</strong>一般涉及比较不常用的算法知识,可以简单看一下,能不能有思路,没有的话,快速过看下面的题就可以了。</li><li><strong>前三道算法题</strong>相对来说难度还可以,涉及模拟和基础算法。可以尝试去想正解,注意多加测试,相信自己是可以拿到这些分数的。</li><li><strong>后四道题</strong>或者加上最后一道题,涉及<strong>图的存储和dfs</strong>可以拿部分分甚至全部分数,其他能模拟的题目也尽量去拿部分分,多想几组测试数据,稳中求胜。</li></ul><p>2.时间:</p><ul><li>在一道题目上不要停留过长的时间,不要超过30-40分钟,可以先放一放,做后面的题,之后可以再回过头来看,可能会有新思路。</li><li>最后一定要留40分钟以上的时间来检查所有题目,把提交的内容再拿回来测试,或是可以模拟拿分的题目再想想有没有更好的办法。最后几分钟再看一下提交的内容有没有问题。</li></ul>]]></content>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>国赛专题训练</title>
<link href="/2024/05/12/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E5%9B%BD%E8%B5%9B%E4%B8%93%E9%A2%98%E8%AE%AD%E7%BB%83/"/>
<url>/2024/05/12/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E5%9B%BD%E8%B5%9B%E4%B8%93%E9%A2%98%E8%AE%AD%E7%BB%83/</url>
<content type="html"><![CDATA[<h2 id="国赛专题训练"><a href="#国赛专题训练" class="headerlink" title="国赛专题训练"></a>国赛专题训练</h2><h3 id="1-暴力-for"><a href="#1-暴力-for" class="headerlink" title="1.暴力-for"></a>1.暴力-for</h3><h4 id="owo"><a href="#owo" class="headerlink" title="owo:"></a>owo:</h4><ul><li>思路:暴力的时候,因为采用的random_shuffle来打乱再计数,那么for的次数越多越好,所以<strong>不必考虑最大的1e6,考虑5000即可</strong>,然后增加for的次数到5e3,这样通过的样例会更多。</li><li>字符串处理:random_shufle(begin, end), 可以打乱数组顺序。str.find(“owo”)返回找到第一个owo的位置, str.find(“owo”, p+1)返回从p+1开始找的第一个owo的位置。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e6</span>+<span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n;<br><span class="hljs-type">int</span> ans;<br>string str[N]; <br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br>cin>>str[i];<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> cnt = <span class="hljs-number">1</span>; cnt <= <span class="hljs-number">5e3</span>; cnt++){<br><span class="hljs-type">int</span> count = <span class="hljs-number">0</span>;<br><span class="hljs-built_in">random_shuffle</span>(str, str+<span class="hljs-number">1</span>+i);<br>string t = <span class="hljs-string">""</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j <= i; j++) t = t + str[j];<br><span class="hljs-type">int</span> p = t.<span class="hljs-built_in">find</span>(<span class="hljs-string">"owo"</span>);<br><span class="hljs-keyword">while</span>(p != <span class="hljs-number">-1</span>){<br>count++;<br>p = t.<span class="hljs-built_in">find</span>(<span class="hljs-string">"owo"</span>, p+<span class="hljs-number">1</span>);<br>}<br>ans = <span class="hljs-built_in">max</span>(ans, count);<br>}<br>cout<<ans<<endl;<br>}<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="子串:"><a href="#子串:" class="headerlink" title="子串:"></a>子串:</h4><ul><li>思路:使用hash,即map来存储所有的子串出现的次数,再对所有的map进行一个计数</li><li>字符串处理:取子串t = s.substr(begin, len)</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e6</span>;<br>string s; <br>unordered_map<string, <span class="hljs-type">int</span>> mp;<br><span class="hljs-type">int</span> res[N];<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>s;<br><span class="hljs-type">int</span> n = s.<span class="hljs-built_in">size</span>();<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> len = <span class="hljs-number">1</span>; len <= n; len++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i + len <span class="hljs-number">-1</span> < n; i++){<br>string t = s.<span class="hljs-built_in">substr</span>(i, len);<br>mp[t]++;<br>} <br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-keyword">auto</span> i:mp){<br><span class="hljs-type">int</span> cnt = i.second;<br>res[cnt]++;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cout<<res[i]<<endl;<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h3 id="2暴力:dfs"><a href="#2暴力:dfs" class="headerlink" title="2暴力:dfs"></a>2暴力:dfs</h3><h4 id="买瓜:"><a href="#买瓜:" class="headerlink" title="买瓜:"></a>买瓜:</h4><ul><li>思路:首先是劈瓜涉及到/2,那么就对所有数*2来避免浮点数的问题。其次,对于每个瓜有三种可能,再加上排序剪枝优化。竟然可以过70%的数据,而且这次写的也比较顺利,思路清晰,很棒!</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">35</span>;<br><span class="hljs-type">int</span> n, m;<br><span class="hljs-type">int</span> a[N];<br><span class="hljs-type">int</span> ans = N;<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> sum, <span class="hljs-type">int</span> cnt)</span></span>{<br><span class="hljs-keyword">if</span>(sum == m){<br>ans = <span class="hljs-built_in">min</span>(ans, cnt);<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-keyword">if</span>(u == n+<span class="hljs-number">1</span>) <span class="hljs-keyword">return</span>;<br><span class="hljs-keyword">if</span>(sum > m) <span class="hljs-keyword">return</span>;<br><span class="hljs-built_in">dfs</span>(u + <span class="hljs-number">1</span>, sum, cnt);<br><span class="hljs-keyword">if</span>(sum + a[u]/<span class="hljs-number">2</span> <= m) <span class="hljs-built_in">dfs</span>(u+<span class="hljs-number">1</span>, sum+a[u]/<span class="hljs-number">2</span>, cnt + <span class="hljs-number">1</span>);<br><span class="hljs-keyword">if</span>(sum + a[u] <= m) <span class="hljs-built_in">dfs</span>(u+<span class="hljs-number">1</span>, sum + a[u], cnt);<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m;<br>m = m*<span class="hljs-number">2</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>a[i];<br>a[i] = a[i]*<span class="hljs-number">2</span>;<br>}<br><span class="hljs-built_in">sort</span>(a+<span class="hljs-number">1</span>, a+<span class="hljs-number">1</span>+n);<br><span class="hljs-built_in">dfs</span>(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);<br><span class="hljs-keyword">if</span>(ans != N) cout<<ans<<endl;<br><span class="hljs-keyword">else</span> cout<<<span class="hljs-string">"-1"</span><<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="01游戏:"><a href="#01游戏:" class="headerlink" title="01游戏:"></a>01游戏:</h4><ul><li>主要采取dfs的方式,对于没填数的每个位子有两种可能,0或1,那么就分别进行dfs,记得恢复现场。当位置到达n+1,1时,根据3条要求进行判断,如果通过,flag= 1,之后的dfs都直接return。再加上fr,fc的剪枝。</li><li>s(i)(j)!=’_’的return少些了,不能再往下走了,另外就是刚开始计数还要考虑下划线,所以if要说清楚。两个漏洞没能通过debug找出来,还是要更加仔细一点。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> n; <br>string s[<span class="hljs-number">15</span>];<br><span class="hljs-type">int</span> fc[<span class="hljs-number">15</span>][<span class="hljs-number">2</span>], fr[<span class="hljs-number">15</span>][<span class="hljs-number">2</span>];<br><span class="hljs-function"><span class="hljs-type">bool</span> <span class="hljs-title">chk</span><span class="hljs-params">(<span class="hljs-type">int</span> x, <span class="hljs-type">int</span> y)</span></span>{<br><span class="hljs-keyword">if</span>(x > <span class="hljs-number">2</span>&&s[x<span class="hljs-number">-1</span>][y]==s[x][y]&&s[x<span class="hljs-number">-2</span>][y]==s[x][y]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br><span class="hljs-keyword">if</span>(y > <span class="hljs-number">2</span>&&s[x][y<span class="hljs-number">-1</span>]==s[x][y]&&s[x][y<span class="hljs-number">-2</span>]==s[x][y]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>}<br><span class="hljs-type">int</span> flag = <span class="hljs-number">0</span>;<br><span class="hljs-type">int</span> A[<span class="hljs-number">1050</span>], B[<span class="hljs-number">1050</span>];<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> x, <span class="hljs-type">int</span> y)</span></span>{<br><span class="hljs-keyword">if</span>(flag) <span class="hljs-keyword">return</span>;<br><span class="hljs-keyword">if</span>(x == n+<span class="hljs-number">1</span> && y == <span class="hljs-number">1</span>){<br><span class="hljs-type">int</span> res = <span class="hljs-number">1</span>; <br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(fr[i][<span class="hljs-number">0</span>]!=n/<span class="hljs-number">2</span> || fr[i][<span class="hljs-number">1</span>]!=n/<span class="hljs-number">2</span>) res = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">if</span>(fc[i][<span class="hljs-number">0</span>]!=n/<span class="hljs-number">2</span> || fc[i][<span class="hljs-number">1</span>]!=n/<span class="hljs-number">2</span>) res = <span class="hljs-number">0</span>;<br>}<br><span class="hljs-keyword">if</span>(res == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;<br><span class="hljs-built_in">memset</span>(A, <span class="hljs-number">0</span>, <span class="hljs-built_in">sizeof</span>(A));<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-type">int</span> tmp = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br>tmp = tmp * <span class="hljs-number">2</span> + s[i][j]-<span class="hljs-string">'0'</span>;<br>}<br><span class="hljs-keyword">if</span>(A[tmp]!=<span class="hljs-number">0</span>) res = <span class="hljs-number">0</span>;<br>A[tmp]++;<br>}<br><span class="hljs-built_in">memset</span>(B, <span class="hljs-number">0</span>, <span class="hljs-built_in">sizeof</span>(B));<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-type">int</span> tmp = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br>tmp = tmp * <span class="hljs-number">2</span> + s[j][i]-<span class="hljs-string">'0'</span>;<br>}<br><span class="hljs-keyword">if</span>(B[tmp]!=<span class="hljs-number">0</span>) res = <span class="hljs-number">0</span>;<br>B[tmp]++;<br>}<br><span class="hljs-keyword">if</span>(res == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br><span class="hljs-keyword">if</span>(i + <span class="hljs-number">2</span> <= n){<br><span class="hljs-keyword">if</span>(s[i][j] == s[i+<span class="hljs-number">1</span>][j]&&s[i][j] == s[i+<span class="hljs-number">2</span>][j]) res = <span class="hljs-number">0</span>;<br>}<br><span class="hljs-keyword">if</span>(j + <span class="hljs-number">2</span> <= n){<br><span class="hljs-keyword">if</span>(s[i][j] == s[i][j+<span class="hljs-number">1</span>]&&s[i][j] == s[i][j+<span class="hljs-number">2</span>]) res = <span class="hljs-number">0</span>;<br>}<br>}<br>}<br><span class="hljs-keyword">if</span>(res == <span class="hljs-number">1</span>){<br>flag = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <=n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br>cout<<s[i][j];<br>}<br>cout<<endl;<br>}<br>}<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-type">int</span> nx = x, ny = y + <span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(ny == n+<span class="hljs-number">1</span>){<br>nx = x + <span class="hljs-number">1</span>;<br>ny = <span class="hljs-number">1</span>;<br>}<br><br><span class="hljs-keyword">if</span>(s[x][y] != <span class="hljs-string">'_'</span>){<br><span class="hljs-built_in">dfs</span>(nx, ny);<br><span class="hljs-keyword">return</span>;<br>}<br><br>s[x][y] = <span class="hljs-string">'0'</span>;<br>fr[x][<span class="hljs-number">0</span>]++;<br>fc[y][<span class="hljs-number">0</span>]++;<br><span class="hljs-keyword">if</span>(fr[x][<span class="hljs-number">0</span>]<=n/<span class="hljs-number">2</span>&&fc[y][<span class="hljs-number">0</span>]<=n/<span class="hljs-number">2</span>&&<span class="hljs-built_in">chk</span>(x, y)) <span class="hljs-built_in">dfs</span>(nx, ny);<br>fr[x][<span class="hljs-number">0</span>]--;<br>fc[y][<span class="hljs-number">0</span>]--;<br><br>s[x][y] = <span class="hljs-string">'1'</span>;<br>fr[x][<span class="hljs-number">1</span>]++;<br>fc[y][<span class="hljs-number">1</span>]++;<br><span class="hljs-keyword">if</span>(fr[x][<span class="hljs-number">1</span>]<=n/<span class="hljs-number">2</span>&&fc[y][<span class="hljs-number">1</span>]<=n/<span class="hljs-number">2</span>&&<span class="hljs-built_in">chk</span>(x, y)) <span class="hljs-built_in">dfs</span>(nx, ny);<br>fr[x][<span class="hljs-number">1</span>]--;<br>fc[y][<span class="hljs-number">1</span>]--;<br>s[x][y] = <span class="hljs-string">'_'</span>;<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>s[i];<br>s[i] = <span class="hljs-string">' '</span>+ s[i];<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br><span class="hljs-keyword">if</span>(s[i][j] == <span class="hljs-string">'0'</span>){<br>fr[i][<span class="hljs-number">0</span>]++;<br>fc[j][<span class="hljs-number">0</span>]++;<br>}<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(s[i][j] == <span class="hljs-string">'1'</span>){<br>fr[i][<span class="hljs-number">1</span>]++;<br>fc[j][<span class="hljs-number">1</span>]++;<br>}<br>}<br>}<br><span class="hljs-built_in">dfs</span>(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>);<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>蓝桥杯2023年国A</title>
<link href="/2024/05/03/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF2023%E5%B9%B4%E5%9B%BDA/"/>
<url>/2024/05/03/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF2023%E5%B9%B4%E5%9B%BDA/</url>
<content type="html"><![CDATA[<h2 id="蓝桥杯2023年国A真题"><a href="#蓝桥杯2023年国A真题" class="headerlink" title="蓝桥杯2023年国A真题"></a>蓝桥杯2023年国A真题</h2><h4 id="C切割"><a href="#C切割" class="headerlink" title="C切割:"></a>C切割:</h4><ul><li>思路:找两个数的最小公因数,从小暴力遍历即可</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> w, h, ans;<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>w>>h;<br><span class="hljs-type">int</span> minn = <span class="hljs-built_in">min</span>(w, h);<br><span class="hljs-type">int</span> maxn = <span class="hljs-built_in">max</span>(w, h);<br><span class="hljs-type">int</span> flag = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">2</span>; i <= minn; i++){<br><span class="hljs-keyword">if</span>(minn % i==<span class="hljs-number">0</span> && maxn %i ==<span class="hljs-number">0</span>){<br>ans = (minn/i)*(maxn/i);<br>cout<<ans<<endl;<br>flag = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">break</span>;<br>}<br>}<br><span class="hljs-keyword">if</span>(!flag){<br>cout<<<span class="hljs-string">"0"</span><<endl;<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="DXYZ:"><a href="#DXYZ:" class="headerlink" title="DXYZ:"></a>DXYZ:</h4><ul><li>思路:先思考1-R的个数,是有规律的,再逐步减去L前面的数,最终可以总结出一个公式。注意,当R<2L,应直接返回,不能使用公式会出错。所以还是要多多考虑特殊情况,多想一些测试用例。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> T;<br><span class="hljs-type">int</span> l, r, sum, res; <br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>T;<br><span class="hljs-keyword">while</span>(T--){<br>cin>>l>>r;<br><span class="hljs-keyword">if</span>(r<<span class="hljs-number">2</span>*l) cout<<<span class="hljs-string">"0"</span><<endl;<br><span class="hljs-keyword">else</span>{<br>sum = r*(r<span class="hljs-number">-1</span>)/<span class="hljs-number">2</span>;<br><span class="hljs-comment">//cout<<"sum:"<<sum<<endl;</span><br>res = (<span class="hljs-number">2</span>*r<span class="hljs-number">-2</span>*l+<span class="hljs-number">1</span>)*(l<span class="hljs-number">-1</span>);<br><span class="hljs-comment">//cout<<"res:"<<res<<endl;</span><br>cout<<sum-res<<endl;<br>}<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:仔细思考是可以做出来的,并不是很难。要多想几组测试用例。</li></ul><h4 id="E第K小的数:"><a href="#E第K小的数:" class="headerlink" title="E第K小的数:"></a>E第K小的数:</h4><h5 id="暴力:"><a href="#暴力:" class="headerlink" title="暴力:"></a>暴力:</h5><ul><li>思路:直接模拟,用vector来装5000*5000个数据, vector的sort写法sort(c.begin(), c.end());</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, m, k;<br><span class="hljs-type">int</span> a[N], b[N];<br>vector <<span class="hljs-type">int</span>> c; <br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m>>k;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++) cin>>a[i];<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= m; i++) cin>>b[i];<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= m; j++){<br>c.<span class="hljs-built_in">push_back</span>(a[i]+b[j]);<br>}<br>} <br><span class="hljs-built_in">sort</span>(c.<span class="hljs-built_in">begin</span>(), c.<span class="hljs-built_in">end</span>());<br> cout<<c[k<span class="hljs-number">-1</span>]<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:可以拿30%分数,注意vector下标从0开始</li></ul><h5 id="正解:二分"><a href="#正解:二分" class="headerlink" title="正解:二分"></a>正解:二分</h5><ul><li>思路:先二分值,来逼近k,然后再套一层二分,固定数组a,二分数组b,找到当前值排第几。两个二分主要要注意边界情况的考虑,l和r的更新</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, m, k;<br><span class="hljs-type">int</span> a[N], b[N];<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">get</span><span class="hljs-params">(<span class="hljs-type">int</span> x)</span></span>{<br><span class="hljs-type">int</span> res = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-type">int</span> l = <span class="hljs-number">1</span>, r = m;<br><span class="hljs-keyword">while</span>(l<r){<br><span class="hljs-type">int</span> mid = l + r + <span class="hljs-number">1</span>>><span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(a[i] + b[mid] > x) r = mid<span class="hljs-number">-1</span>;<br><span class="hljs-keyword">else</span> l = mid;<br>}<br><span class="hljs-keyword">if</span>(a[i] + b[l] <= x)res += l;<br>}<br><span class="hljs-keyword">return</span> res;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m>>k;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++) cin>>a[i];<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= m; i++) cin>>b[i];<br><span class="hljs-built_in">sort</span>(a+<span class="hljs-number">1</span>, a+<span class="hljs-number">1</span>+n);<br><span class="hljs-built_in">sort</span>(b+<span class="hljs-number">1</span>, b+<span class="hljs-number">1</span>+m);<br><span class="hljs-type">int</span> l = <span class="hljs-number">1</span>, r = <span class="hljs-number">1e18</span>;<br><span class="hljs-keyword">while</span>(l<r){<br><span class="hljs-type">int</span> mid = l + r>><span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">get</span>(mid)>=k) r = mid;<br><span class="hljs-keyword">else</span> l = mid + <span class="hljs-number">1</span>;<br>} <br>cout<<l<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>去思考暴力手法为什么复杂度高,如何简化,像这道题,存在很明显的递增性,两次二分就可以解决,不要局限于一次的情况,学习了。</li></ul><h4 id="F相连的边:"><a href="#F相连的边:" class="headerlink" title="F相连的边:"></a>F相连的边:</h4><ul><li>思路:取边长和最大的连在一起的三条边有两种可能性,一是三条边有一个共同端点,二是三条边依次相连。对于一的话,可以遍历所有点,把它所在的边按边长进行倒叙排序,取前三条即可;对于二的话,遍历所有边,对于它的两个端点找最大的边长,但不能和当前这条边重复,可以给每条边一个id来区分。使用vector来存储每个点对应的边,手写自定义排序。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">2e5</span>+<span class="hljs-number">10</span>;<br><span class="hljs-keyword">struct</span> <span class="hljs-title class_">edge</span>{<br><span class="hljs-type">int</span> x, y, l, id;<br>}e[N];<br>vector<edge> node[N];<br><span class="hljs-type">int</span> n, ans;<br><span class="hljs-function"><span class="hljs-type">bool</span> <span class="hljs-title">cmp</span><span class="hljs-params">(edge a, edge b)</span></span>{<br><span class="hljs-keyword">return</span> a.l>b.l;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i < n; i++){<br><span class="hljs-type">int</span> x, l;<br>cin>>x>>l;<br>e[i] = {x, i+<span class="hljs-number">1</span>, l, i};<br>node[x].<span class="hljs-built_in">push_back</span>(e[i]);<br>node[i+<span class="hljs-number">1</span>].<span class="hljs-built_in">push_back</span>(e[i]); <br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-built_in">sort</span>(node[i].<span class="hljs-built_in">begin</span>(), node[i].<span class="hljs-built_in">end</span>(), cmp);<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(node[i].<span class="hljs-built_in">size</span>()>=<span class="hljs-number">3</span>){<br>ans = <span class="hljs-built_in">max</span>(ans, node[i][<span class="hljs-number">0</span>].l+node[i][<span class="hljs-number">1</span>].l+node[i][<span class="hljs-number">2</span>].l);<br>}<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i < n; i++){<br><span class="hljs-type">int</span> x = e[i].x, y = e[i].y, l = e[i].l, id = e[i].id;<br><span class="hljs-type">int</span> tmp = l;<br><span class="hljs-keyword">if</span>(node[x].<span class="hljs-built_in">size</span>()><span class="hljs-number">1</span>){<br>tmp += node[x][<span class="hljs-number">0</span>].id == id? node[x][<span class="hljs-number">1</span>].l : node[x][<span class="hljs-number">0</span>].l;<br>}<br><span class="hljs-keyword">if</span>(node[y].<span class="hljs-built_in">size</span>()><span class="hljs-number">1</span>){<br>tmp += node[y][<span class="hljs-number">0</span>].id == id? node[y][<span class="hljs-number">1</span>].l : node[y][<span class="hljs-number">0</span>].l;<br>}<br>ans = <span class="hljs-built_in">max</span>(ans, tmp);<br>}<br>cout<<ans<<endl; <br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:首先对问题进行分类,涉及到树的存储,使用vector,实际上并不难,只是需要经验。尤其是这种树上的问题,多做多积累经验。</li></ul><h4 id="G01游戏:"><a href="#G01游戏:" class="headerlink" title="G01游戏:"></a>G01游戏:</h4><ul><li>思路:使用dfs+剪枝,有两种情况0或1,再往下深入,直到所有都遍历过了,验证矩阵是否合法:所有行和列不能相同,使用状压数组来记录,不能有连续三个相同。合法的话就直接在dfs里输出,并将flag置为1,后续的dfs陆续return。剪枝:在遍历过程中验证是否和前两个(行,列)相同,0,1个数是否<=n/2。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">12</span>;<br>string s[N];<br><span class="hljs-type">int</span> n, flag =<span class="hljs-number">0</span>;<br><span class="hljs-type">int</span> fr[N][<span class="hljs-number">2</span>], fc[N][<span class="hljs-number">2</span>];<br><span class="hljs-type">int</span> A[<span class="hljs-number">1050</span>], B[<span class="hljs-number">1050</span>];<br><span class="hljs-function"><span class="hljs-type">bool</span> <span class="hljs-title">chk</span><span class="hljs-params">(<span class="hljs-type">int</span> x, <span class="hljs-type">int</span> y)</span></span>{<br><span class="hljs-keyword">if</span>(x><span class="hljs-number">2</span>&&s[x<span class="hljs-number">-1</span>][y]==s[x][y]&&s[x<span class="hljs-number">-2</span>][y]==s[x][y]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br><span class="hljs-keyword">if</span>(y><span class="hljs-number">2</span>&&s[x][y<span class="hljs-number">-1</span>]==s[x][y]&&s[x][y<span class="hljs-number">-2</span>]==s[x][y]) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">bfs</span><span class="hljs-params">(<span class="hljs-type">int</span> x, <span class="hljs-type">int</span> y)</span></span>{<br><span class="hljs-keyword">if</span>(flag == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span>;<br><span class="hljs-keyword">if</span>(x == n+<span class="hljs-number">1</span> && y == <span class="hljs-number">1</span>){<br><span class="hljs-type">int</span> res = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">2</span>; j < n; j++) <span class="hljs-keyword">if</span>(s[i][j] == s[i][j<span class="hljs-number">-1</span>] && s[i][j] == s[i][j+<span class="hljs-number">1</span>]) res = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">2</span>; j < n; j++) <span class="hljs-keyword">if</span>(s[j][i] == s[j<span class="hljs-number">-1</span>][i] && s[j][i] == s[j+<span class="hljs-number">1</span>][i]) res = <span class="hljs-number">0</span>;<br>}<br><span class="hljs-keyword">if</span>(res == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;<br><span class="hljs-built_in">memset</span>(A,<span class="hljs-number">0</span>,<span class="hljs-built_in">sizeof</span>(A));<br><span class="hljs-built_in">memset</span>(B,<span class="hljs-number">0</span>,<span class="hljs-built_in">sizeof</span>(B)); <br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-type">int</span> tmp = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br>tmp = tmp*<span class="hljs-number">2</span> + s[i][j]-<span class="hljs-string">'0'</span>;<br>}<br><span class="hljs-keyword">if</span>(A[tmp]) res = <span class="hljs-number">0</span>;<br>A[tmp]++;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-type">int</span> tmp = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br>tmp = tmp*<span class="hljs-number">2</span> + s[j][i]-<span class="hljs-string">'0'</span>;<br>}<br><span class="hljs-keyword">if</span>(B[tmp]) res = <span class="hljs-number">0</span>;<br>B[tmp]++;<br>}<br><span class="hljs-keyword">if</span>(!res) <span class="hljs-keyword">return</span>;<br>flag = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i<=n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n ;j++){<br>cout<<s[i][j];<br>}<br>cout<<endl;<br>}<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-type">int</span> a = x, b = y;<br>b++;<br><span class="hljs-keyword">if</span>(b==n+<span class="hljs-number">1</span>) a++, b=<span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(s[x][y]!=<span class="hljs-string">'_'</span>){<br><span class="hljs-built_in">bfs</span>(a, b);<br><span class="hljs-keyword">return</span>;<br>}<br>s[x][y] = <span class="hljs-string">'0'</span>;<br>fr[x][<span class="hljs-number">0</span>]++;<br>fc[y][<span class="hljs-number">0</span>]++;<br><span class="hljs-keyword">if</span>(fr[x][<span class="hljs-number">0</span>]<=n/<span class="hljs-number">2</span>&&fc[y][<span class="hljs-number">0</span>]<=n/<span class="hljs-number">2</span>&&<span class="hljs-built_in">chk</span>(x,y)) <span class="hljs-built_in">bfs</span>(a, b);<br>fr[x][<span class="hljs-number">0</span>]--;<br>fc[y][<span class="hljs-number">0</span>]--;<br><br>s[x][y] = <span class="hljs-string">'1'</span>;<br>fr[x][<span class="hljs-number">1</span>]++;<br>fc[y][<span class="hljs-number">1</span>]++;<br><span class="hljs-keyword">if</span>(fr[x][<span class="hljs-number">1</span>]<=n/<span class="hljs-number">2</span>&&fc[y][<span class="hljs-number">1</span>]<=n/<span class="hljs-number">2</span>&&<span class="hljs-built_in">chk</span>(x,y)) <span class="hljs-built_in">bfs</span>(a, b);<br>fr[x][<span class="hljs-number">1</span>]--;<br>fc[y][<span class="hljs-number">1</span>]--;<br>s[x][y]=<span class="hljs-string">'_'</span>; <span class="hljs-comment">//记得回复现场</span><br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>s[i];<br>s[i] = <span class="hljs-string">' '</span>+s[i];<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br><span class="hljs-keyword">if</span>(s[i][j] == <span class="hljs-string">'0'</span>){<br>fr[i][<span class="hljs-number">0</span>]++;<br>fc[j][<span class="hljs-number">0</span>]++;<br>}<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(s[i][j] == <span class="hljs-string">'1'</span>){<br>fr[i][<span class="hljs-number">1</span>]++;<br>fc[j][<span class="hljs-number">1</span>]++;<br>}<br>}<br>}<br><span class="hljs-built_in">bfs</span>(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>);<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>要先理清思路再开始写,尤其是dfs(bfs),主要是截止判断,下一个dfs的写法,还是要多多练习。并没有想象的那么复杂。</li></ul><h4 id="H子串暴力:"><a href="#H子串暴力:" class="headerlink" title="H子串暴力:"></a>H子串暴力:</h4><ul><li>思路: 统计出现次数为1-n的子串个数,可以采用map统计所有子串的出现次数,再遍历所有map来对出现次数进行一个计数即可。可以过25%。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e6</span>+<span class="hljs-number">10</span>;<br>string s; <br>unordered_map<string, <span class="hljs-type">int</span>> mp;<br><span class="hljs-type">int</span> cnt[N];<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>s;<br><span class="hljs-type">int</span> n = s.<span class="hljs-built_in">size</span>();<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> len = <span class="hljs-number">1</span>; len <= n; len++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i+len<span class="hljs-number">-1</span><n; i++){<br>string t = s.<span class="hljs-built_in">substr</span>(i, len); <br>mp[t]++;<br>}<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-keyword">auto</span> i:mp){<br><span class="hljs-type">int</span> t = i.second;<br>cnt[t]++;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cout<<cnt[i]<<endl;<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>需要掌握map的使用以及获取,还有字符串的处理。遍历所有字串可以先遍历长度再遍历起始点,使用substr来获取子串,遍历所有map可以采取auto,获取次数(map的映射值)可以使用i.second。</li></ul><h4 id="I树上的路径暴力:"><a href="#I树上的路径暴力:" class="headerlink" title="I树上的路径暴力:"></a>I树上的路径暴力:</h4><ul><li>计算任意两个点的距离需要用到lca算法,再枚举所有两个点的组合,可以过65%,太牛了!是可以做到的。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e6</span>+<span class="hljs-number">10</span>;<br><span class="hljs-keyword">typedef</span> pair<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> PII;<br><span class="hljs-type">int</span> n, l, r, sum[N], ans;<br>vector<PII> e[N];<br><span class="hljs-type">int</span> siz[N], dep[N], top[N], fa[N], son[N];<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs1</span><span class="hljs-params">(<span class="hljs-type">int</span> u ,<span class="hljs-type">int</span> father)</span></span>{<span class="hljs-comment">//(1,0)</span><br>siz[u] = <span class="hljs-number">1</span>;<br>dep[u] = dep[father] + <span class="hljs-number">1</span>;<br>fa[u] = father;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> s = e[u][i].first;<br><span class="hljs-keyword">if</span>(s == fa[u]) <span class="hljs-keyword">continue</span>;<br><span class="hljs-built_in">dfs1</span>(s, u);<br>siz[u] += siz[s];<br><span class="hljs-keyword">if</span>(siz[son[u]] < siz[s]){<br>son[u] = s;<br>}<br>}<br>}<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs2</span><span class="hljs-params">(<span class="hljs-type">int</span> u ,<span class="hljs-type">int</span> t)</span></span>{<span class="hljs-comment">//(1,1)</span><br>top[u] = t;<br><span class="hljs-keyword">if</span>(son[u] == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;<br><span class="hljs-built_in">dfs2</span>(son[u], t);<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> s = e[u][i].first;<br><span class="hljs-keyword">if</span>(s == fa[u] || s == son[u]) <span class="hljs-keyword">continue</span>;<br><span class="hljs-built_in">dfs2</span>(s, s);<br>}<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">lca</span><span class="hljs-params">(<span class="hljs-type">int</span> x, <span class="hljs-type">int</span> y)</span></span>{<br><span class="hljs-keyword">while</span>(top[x] != top[y]){<br><span class="hljs-keyword">if</span>(dep[top[x]] < dep[top[y]]){<br><span class="hljs-built_in">swap</span>(x, y);<br>}<br>x = fa[top[x]];<br>}<br><span class="hljs-keyword">return</span> dep[x] < dep[y]? x : y;<br>}<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">cal_sum</span><span class="hljs-params">(<span class="hljs-type">int</span> u)</span></span>{<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> x = e[u][i].first;<br><span class="hljs-keyword">if</span>(x == fa[u]) <span class="hljs-keyword">continue</span>;<br><span class="hljs-type">int</span> y = e[u][i].second;<br>sum[x] = sum[u] + y;<br><span class="hljs-built_in">cal_sum</span>(x);<br>}<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>l>>r;<br><br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>,x; i < n; i++){<br>cin>>x;<br>e[x].<span class="hljs-built_in">push_back</span>({i + <span class="hljs-number">1</span>,<span class="hljs-number">1</span>});<br>e[i+<span class="hljs-number">1</span>].<span class="hljs-built_in">push_back</span>({x, <span class="hljs-number">1</span>});<br>}<br><span class="hljs-built_in">dfs1</span>(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>);<br><span class="hljs-built_in">dfs2</span>(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>);<br><span class="hljs-built_in">cal_sum</span>(<span class="hljs-number">1</span>);<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = i + <span class="hljs-number">1</span>; j <=n; j++){<br><span class="hljs-type">int</span> dis = sum[i]+sum[j]<span class="hljs-number">-2</span>*sum[<span class="hljs-built_in">lca</span>(i,j)];<br><span class="hljs-comment">//cout<<"i:"<<i<<" j:"<<j<<" dis:"<<dis<<endl;</span><br><span class="hljs-keyword">if</span>(dis>=l&&dis<=r){<br>ans+=dis;<br>}<br>}<br>} <br>cout<<ans<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:lca还是比较常用的算法,要熟练掌握,另外暴力计算树上两点的距离也要熟练才行。</li></ul>]]></content>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>2022年蓝桥杯国A总结</title>
<link href="/2024/05/03/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/2022%E5%B9%B4%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BDA%E6%80%BB%E7%BB%93/"/>
<url>/2024/05/03/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/2022%E5%B9%B4%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BDA%E6%80%BB%E7%BB%93/</url>
<content type="html"><![CDATA[<h2 id="蓝桥杯2022年第十三届国赛真题总结"><a href="#蓝桥杯2022年第十三届国赛真题总结" class="headerlink" title="蓝桥杯2022年第十三届国赛真题总结"></a>蓝桥杯2022年第十三届国赛真题总结</h2><h4 id="A小蓝与钥匙:"><a href="#A小蓝与钥匙:" class="headerlink" title="A小蓝与钥匙:"></a>A小蓝与钥匙:</h4><ul><li>错排,需要提前接触过,或者理解清楚题意,自己找规律总结</li></ul><h4 id="B排列距离:"><a href="#B排列距离:" class="headerlink" title="B排列距离:"></a>B排列距离:</h4><ul><li>康托展开,也需要一定算法基础</li></ul><h4 id="C内存空间:"><a href="#C内存空间:" class="headerlink" title="C内存空间:"></a>C内存空间:</h4><ul><li>分类模拟题,字符串处理,细心一点是可以做出来的</li></ul><h4 id="D最大公约数:"><a href="#D最大公约数:" class="headerlink" title="D最大公约数:"></a>D最大公约数:</h4><ul><li>暴力可以拿80%的分数,并不难,可以做出来的</li></ul><h4 id="E-owo"><a href="#E-owo" class="headerlink" title="E owo:"></a>E owo:</h4><ul><li>采取随机的方法暴力,要对字符串相关处理比较熟悉,可以拿30%分数</li></ul><h4 id="F环境治理:"><a href="#F环境治理:" class="headerlink" title="F环境治理:"></a>F环境治理:</h4><ul><li>二分+Floyed,两个算法都要比较熟练才行</li></ul><h4 id="G选素数"><a href="#G选素数" class="headerlink" title="G选素数:"></a>G选素数:</h4><ul><li>数学题,结合了线性筛,有暴力的可能,首先需要研究出题眼是找最大质因子</li></ul><h4 id="H替换字符:"><a href="#H替换字符:" class="headerlink" title="H替换字符:"></a>H替换字符:</h4><ul><li>暴力即可,可以拿到一半左右分数</li></ul><h4 id="I三角序列:"><a href="#I三角序列:" class="headerlink" title="I三角序列:"></a>I三角序列:</h4><ul><li>暴力模拟+二分,有多个函数嵌套实现,需要仔细分析分解题意</li></ul><h4 id="分数分布:5-5-10-10-15-15-20-20-25-25-150分"><a href="#分数分布:5-5-10-10-15-15-20-20-25-25-150分" class="headerlink" title="分数分布:5+5+10+10+15+15+20+20+25+25=150分"></a>分数分布:5+5+10+10+15+15+20+20+25+25=150分</h4><h4 id="总结:"><a href="#总结:" class="headerlink" title="总结:"></a>总结:</h4><ul><li>暴力还是很重要的,可以拿到不少分数,可以总结一些常用的暴力手段</li><li>基础算法比如二分,Floyed所属的图论,要很熟练</li><li>进阶算法:错排,康托展开,线性筛都可以多多学习接触一下,真的考到了是事半功倍的</li><li>===>还是把精力放在<strong>暴力和基础算法的训练</strong>上,进阶算法可以适当地学习,还有就是心态的训练,前两道选择题没思路可以先果断跳过,后面分数比重更高,机会更多</li></ul><h2 id="蓝桥杯2023年第十四届国赛真题总结"><a href="#蓝桥杯2023年第十四届国赛真题总结" class="headerlink" title="蓝桥杯2023年第十四届国赛真题总结"></a>蓝桥杯2023年第十四届国赛真题总结</h2><h4 id="AB填空题:"><a href="#AB填空题:" class="headerlink" title="AB填空题:"></a>AB填空题:</h4><ul><li>涉及到的是比较不常用的算法,不了解算法的话也很难暴力,性价比不高,于是跳过</li></ul><h4 id="C切割:"><a href="#C切割:" class="headerlink" title="C切割:"></a>C切割:</h4><ul><li>模拟暴力求解,比较简单的一道题目</li></ul><h4 id="DXYZ:"><a href="#DXYZ:" class="headerlink" title="DXYZ:"></a>DXYZ:</h4><ul><li>规律题,有特殊情况需要考虑,需要出一些测试样例会比较保险</li></ul><h4 id="E第K小的数:"><a href="#E第K小的数:" class="headerlink" title="E第K小的数:"></a>E第K小的数:</h4><ul><li>暴力:使用vector数组+sort即可,代码简单</li><li>正解:二分+二分,二分的判定条件也要考虑妥当,理清思路后并不难写。这方面的思维可以再多多锻炼</li></ul><h4 id="F相连的边:"><a href="#F相连的边:" class="headerlink" title="F相连的边:"></a>F相连的边:</h4><ul><li>分类讨论,涉及图的存储,边的排序,思路并不难,但是不够熟练这一类的题目</li></ul><h4 id="G01游戏"><a href="#G01游戏" class="headerlink" title="G01游戏:"></a>G01游戏:</h4><ul><li>dfs+剪枝,对于dfs思路清晰比较重要,写的过程中发现思路还有优点混乱需要在dfs这再多多练习。dfs的写法有多种,但要找到一种自己熟悉的模式,固定下来。</li></ul><h4 id="H子串:"><a href="#H子串:" class="headerlink" title="H子串:"></a>H子串:</h4><ul><li>用map来实现字符串hash,可以多多了解字符串的常见处理以及map这些常用stl的用法</li></ul><h4 id="I树上的路径:"><a href="#I树上的路径:" class="headerlink" title="I树上的路径:"></a>I树上的路径:</h4><ul><li>用LCA暴力可以获得不少分数,证明了这一算法的重要性,需要熟练掌握。</li></ul><h4 id="总结:-1"><a href="#总结:-1" class="headerlink" title="总结:"></a>总结:</h4><ul><li>首先先打一剂强心针,两年的真题过下来,再增强当前基础的前提下,是有可能拿到国二的,要有信心</li><li>需要加强的基础算法:<ul><li>图的存储: 包括最短路算法</li><li>dfs暴力:各种图上的搜索</li><li>lca:板子要特别熟悉,包括cal_sum这个函数</li><li>补充:线性筛,并查集,字符串处理,map处理,dp基础题</li></ul></li><li>稳扎稳打,除了前两道题和最后一道题,其他题目都是可以争取部分分数的。</li></ul>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>蓝桥杯</tag>
</tags>
</entry>
<entry>
<title>算法概念和板子整理</title>
<link href="/2024/04/21/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E7%AE%97%E6%B3%95%E6%A6%82%E5%BF%B5%E5%92%8C%E6%9D%BF%E5%AD%90%E6%95%B4%E7%90%86/"/>
<url>/2024/04/21/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E7%AE%97%E6%B3%95%E6%A6%82%E5%BF%B5%E5%92%8C%E6%9D%BF%E5%AD%90%E6%95%B4%E7%90%86/</url>
<content type="html"><![CDATA[<h2 id="一些算法概念和板子集中整理"><a href="#一些算法概念和板子集中整理" class="headerlink" title="一些算法概念和板子集中整理"></a>一些算法概念和板子集中整理</h2><h3 id="算法概念:"><a href="#算法概念:" class="headerlink" title="算法概念:"></a>算法概念:</h3><h4 id="1-错排:"><a href="#1-错排:" class="headerlink" title="1.错排:"></a>1.错排:</h4><ul><li>n个有序的元素应有n!个不同的排列,如若一个排列使得所有的元素不在原来的位置上,则称这个排列为错排</li><li>d[1] = 0, d[2] = 1,d[3] = 2</li><li>d[n] = (n-1)*(d[n-1]+d[n-2]) 数据一般较大,开long long</li></ul><h4 id="2-康托展开:"><a href="#2-康托展开:" class="headerlink" title="2.康托展开:"></a>2.康托展开:</h4><ul><li><p><strong>康托展开</strong>是一个全排列到一个自然数的映射,从0开始编号,全排列的字符串中某一个的编号是<strong>ai*f[len-1-i]</strong>,ai表示后面小于当前数字的个数,f数组表示阶乘</p></li><li><p><strong>康托逆展开</strong>,给定一个自然数,求对应的全排列中的某一个字符串</p><ul><li><p>如果初始序列是12345(第一个),让你求第107个序列是什么。(按字典序递增)</p><p>先把107减1,因为康托展开里的初始序列编号为0<br>然后计算下后缀积:<br> 1 2 3 4 5<br> 5! 4! 3! 2!1! 0!<br>120 24 6 2 1 1</p><p>106 / 4! = 4 ······ 10 有4个比它小的所以因该是5 从(1,2,3,4,5)里选<br>10 / 3! = 1 ······ 4 有1个比它小的所以因该是2 从(1, 2, 3, 4)里选<br> 4 / 2! = 2 ······ 0 有2个比它小的所以因该是4 从(1, 3, 4)里选<br> 0 / 1! = 0 ······ 0 有0个比它小的所以因该是1 从(1,3)里选<br> 0 / 0! = 0 ······ 0 有0个比它小的所以因该是3 从(3)里选</p><p>所以编号107的是 52413</p></li></ul></li><li><p>代码:</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">20</span>;<br><span class="hljs-type">int</span> f[<span class="hljs-number">25</span>];<br><span class="hljs-type">int</span> num;<br>vector<<span class="hljs-type">char</span>> vec;<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">jie_cheng</span><span class="hljs-params">(<span class="hljs-type">int</span> n)</span></span>{<br>f[<span class="hljs-number">0</span>] = f[<span class="hljs-number">1</span>] = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">2</span>; i <= n; i++){<br>f[i] = i * f[i<span class="hljs-number">-1</span>];<br>}<br><span class="hljs-keyword">return</span>;<br>} <br><span class="hljs-function">string <span class="hljs-title">re_kangtuo</span><span class="hljs-params">(<span class="hljs-type">int</span> k)</span></span>{<br><span class="hljs-type">int</span> n = vec.<span class="hljs-built_in">size</span>();<br>k--;<br>string ans = <span class="hljs-string">""</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-type">int</span> t = k / f[n-i];<br>ans += vec[t];<br>k %= f[n-i];<br>vec.<span class="hljs-built_in">erase</span>(vec.<span class="hljs-built_in">begin</span>()+t);<br>}<br><span class="hljs-keyword">return</span> ans;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-built_in">jie_cheng</span>(N);<br><span class="hljs-type">int</span> x = <span class="hljs-number">107</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= N; i++){<br><span class="hljs-keyword">if</span>(x / f[i] == <span class="hljs-number">0</span>){<br>num = i;<br><span class="hljs-keyword">break</span>;<br>}<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= num; i++){<br>vec.<span class="hljs-built_in">push_back</span>(<span class="hljs-string">'0'</span> + i);<br>}<br>cout<<<span class="hljs-built_in">re_kangtuo</span>(x)<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="3-线性筛:"><a href="#3-线性筛:" class="headerlink" title="3.线性筛:"></a>3.线性筛:</h4><ul><li>O[N]的时间复杂度来求一个范围内的素数。<strong>i % prime[j] == 0</strong>是关键,举例30=2 * 15 = 10 * 3,为了使得30只筛除一次,当i = 10时,发现i%prime[j] (2) == 0,说明之后的数字也均可以被2整除,所以跳出j的for循环,把筛除的机会留到后面,即用最小的质因子去筛。</li><li>另外,在这个过程中还可以求一个范围内所有数的最大质因子</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Linear_sieve</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">2</span>; i <= n; i++){<br>isprime[i] = <span class="hljs-literal">true</span>;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">2</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(isprime[i]){<br>t++;<br>prime[t] = i;<br><span class="hljs-comment">//p[i] = i;</span><br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= t&&prime[j]*i<=n; j++){<br><span class="hljs-comment">//p[prime[j]*i] = max(p[i], prime[j]);</span><br>isprime[prime[j]*i] = <span class="hljs-literal">false</span>;<br><span class="hljs-keyword">if</span>(i % prime[j] == <span class="hljs-number">0</span>){<br><span class="hljs-keyword">break</span>;<br>}<br>}<br>}<br>}<br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>蓝桥杯</tag>
</tags>
</entry>
<entry>
<title>4.20学术节</title>
<link href="/2024/04/21/%E7%94%9F%E6%B4%BB%E4%B8%8E%E6%8A%80%E6%9C%AF/4-20%E5%AD%A6%E6%9C%AF%E8%8A%82/"/>
<url>/2024/04/21/%E7%94%9F%E6%B4%BB%E4%B8%8E%E6%8A%80%E6%9C%AF/4-20%E5%AD%A6%E6%9C%AF%E8%8A%82/</url>
<content type="html"><![CDATA[<h2 id="4-20学校学术节"><a href="#4-20学校学术节" class="headerlink" title="4.20学校学术节"></a>4.20学校学术节</h2><h4 id="小节:"><a href="#小节:" class="headerlink" title="小节:"></a>小节:</h4><p>超出预期的一场学术活动</p><p>上午的学术大佬们汇报分享最前沿的技术和做科研的心得</p><p>下午十研究生学长学姐们分享论文展板</p><p>大大开拓了眼界</p><h4 id="一些记录:"><a href="#一些记录:" class="headerlink" title="一些记录:"></a>一些记录:</h4><img src="01.jpg" alt="02" width="400px"><p>青年教师科研的分享</p><img src="02.jpg" alt="02" width="400px"><p>大部分老师分享的都与大模型AI相关</p><img src="03.jpg" alt="03" width="400px"><p>作为小白,在学长的解说下也明白了做的是什么,怎么做的。表达逻辑非常清晰简洁,超级厉害👍</p>]]></content>
<categories>
<category>人文</category>
</categories>
<tags>
<tag>活动</tag>
</tags>
</entry>
<entry>
<title>第十三届蓝桥杯国赛真题训练</title>
<link href="/2024/04/20/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E7%AC%AC%E5%8D%81%E4%B8%89%E5%B1%8A%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E7%9C%9F%E9%A2%98%E8%AE%AD%E7%BB%83/"/>
<url>/2024/04/20/%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E5%A4%87%E8%B5%9B/%E7%AC%AC%E5%8D%81%E4%B8%89%E5%B1%8A%E8%93%9D%E6%A1%A5%E6%9D%AF%E5%9B%BD%E8%B5%9B%E7%9C%9F%E9%A2%98%E8%AE%AD%E7%BB%83/</url>
<content type="html"><![CDATA[<h2 id="2022年蓝桥杯国赛真题"><a href="#2022年蓝桥杯国赛真题" class="headerlink" title="2022年蓝桥杯国赛真题"></a>2022年蓝桥杯国赛真题</h2><h4 id="A小蓝于钥匙:"><a href="#A小蓝于钥匙:" class="headerlink" title="A小蓝于钥匙:"></a>A小蓝于钥匙:</h4><ul><li>思路:主要在于C14 28的求解以及错排的求解。错排是一种基于推导可以得出的dp,D[n] = (n-1)*(D[n-1]+D[n-2])</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span> <span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> ans = <span class="hljs-number">1</span>;<br><span class="hljs-type">int</span> d[<span class="hljs-number">20</span>];<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span> </span>{<br> <span class="hljs-type">int</span> cnt = <span class="hljs-number">2</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">15</span>; i <= <span class="hljs-number">28</span>; i++){<br> ans = ans * i;<br> <span class="hljs-keyword">while</span>(ans % cnt == <span class="hljs-number">0</span> && cnt <= <span class="hljs-number">14</span>){<br> ans /= cnt;<br> cnt++;<br>}<br>}<br>d[<span class="hljs-number">2</span>] = <span class="hljs-number">1</span>;<br>d[<span class="hljs-number">3</span>] = <span class="hljs-number">2</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">3</span>; i <= <span class="hljs-number">14</span>; i++){<br>d[i] = <span class="hljs-number">1ll</span>*(i<span class="hljs-number">-1</span>) *(d[i<span class="hljs-number">-1</span>] + d[i<span class="hljs-number">-2</span>]);<br>}<br>cout<<ans*d[<span class="hljs-number">14</span>]<<endl;<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:要理解清楚题意,搞清概念,学习了错排这一算法</li></ul><h4 id="B排列距离:"><a href="#B排列距离:" class="headerlink" title="B排列距离:"></a>B排列距离:</h4><ul><li>思路:康托展开,从0开始编号,全排列的字符串中某一个的编号是<strong>ai*f[len-1-i]</strong>,ai表示后面小于当前数字的个数,f数组表示阶乘。注意最终比较大小时的边界问题。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">20</span>;<br><span class="hljs-type">int</span> f[<span class="hljs-number">21</span>];<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">jie_cheng</span><span class="hljs-params">(<span class="hljs-type">int</span> n)</span></span>{<br>f[<span class="hljs-number">0</span>] = f[<span class="hljs-number">1</span>] = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">2</span>; i <= n; i++){<br>f[i] = i * f[i<span class="hljs-number">-1</span>];<br>}<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">kangtuo</span><span class="hljs-params">(string str)</span></span>{<br><span class="hljs-type">int</span> len = str.<span class="hljs-built_in">length</span>();<br><span class="hljs-type">int</span> ans = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < len; i++){<br><span class="hljs-type">int</span> tmp = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = i + <span class="hljs-number">1</span>; j < len; j++){<br><span class="hljs-keyword">if</span>(str[i] > str[j]) tmp++;<br>}<br>ans += tmp * f[len<span class="hljs-number">-1</span>-i];<br>}<br><span class="hljs-keyword">return</span> ans;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-built_in">jie_cheng</span>(N);<br><span class="hljs-type">int</span> s1 = <span class="hljs-built_in">kangtuo</span>(<span class="hljs-string">"aejcldbhpiogfqnkr"</span>);<br><span class="hljs-type">int</span> s2 = <span class="hljs-built_in">kangtuo</span>(<span class="hljs-string">"ncfjboqiealhkrpgd"</span>);<br><span class="hljs-type">int</span> ans = <span class="hljs-built_in">min</span>(s2-s1,f[<span class="hljs-number">17</span>]-(s2-s1));<br>cout<<ans<<endl;<br><br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="C内存空间:"><a href="#C内存空间:" class="headerlink" title="C内存空间:"></a>C内存空间:</h4><ul><li>思路:模拟题,主要考验字符串的处理,逐行输入,采用getline(cin, s)。另外,cin>>t之后要getchar()取走一个换行符。先分好类,再逐个实现,并不难。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> t, ans, a[<span class="hljs-number">4</span>];<br>string s, mp[<span class="hljs-number">4</span>] = {<span class="hljs-string">"GB"</span>, <span class="hljs-string">"MB"</span>, <span class="hljs-string">"KB"</span>, <span class="hljs-string">"B"</span>};<br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">solve1</span><span class="hljs-params">()</span></span>{<br><span class="hljs-type">int</span> m, num = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">if</span>(s[<span class="hljs-number">0</span>] == <span class="hljs-string">'i'</span>) m = <span class="hljs-number">4</span>;<br><span class="hljs-keyword">else</span> m = <span class="hljs-number">8</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < s.<span class="hljs-built_in">length</span>(); i++){<br><span class="hljs-keyword">if</span>(s[i] == <span class="hljs-string">'='</span>){<br>num ++;<br>}<br>}<br>ans += num*m;<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">solve2</span><span class="hljs-params">()</span></span>{<br><span class="hljs-type">int</span> m;<br><span class="hljs-keyword">if</span>(s[<span class="hljs-number">0</span>] == <span class="hljs-string">'i'</span>) m = <span class="hljs-number">4</span>;<br><span class="hljs-keyword">else</span> m = <span class="hljs-number">8</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < s.<span class="hljs-built_in">length</span>(); i++){<br><span class="hljs-keyword">if</span>(s[i] == <span class="hljs-string">'['</span>){<br><span class="hljs-type">int</span> num = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = i + <span class="hljs-number">1</span>; s[j] != <span class="hljs-string">']'</span>; j++){<br>num = num * <span class="hljs-number">10</span> + (s[j]-<span class="hljs-string">'0'</span>);<br>}<br>ans += m*num;<br>}<br>}<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">solve3</span><span class="hljs-params">()</span></span>{<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < s.<span class="hljs-built_in">length</span>(); i++){<br><span class="hljs-keyword">if</span>(s[i] == <span class="hljs-string">'"'</span> && s[i<span class="hljs-number">-1</span>] == <span class="hljs-string">'='</span>){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = i + <span class="hljs-number">1</span>; s[j] != <span class="hljs-string">'"'</span>; j++){<br>ans++;<br>}<br>}<br>}<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>t;<br><span class="hljs-built_in">getchar</span>();<br><span class="hljs-keyword">while</span>(t--){<br><span class="hljs-built_in">getline</span>(cin, s);<br><span class="hljs-keyword">if</span>((s[<span class="hljs-number">0</span>] == <span class="hljs-string">'i'</span> && s[<span class="hljs-number">3</span>] == <span class="hljs-string">'['</span>)|| (s[<span class="hljs-number">0</span>] == <span class="hljs-string">'l'</span> && s[<span class="hljs-number">4</span>] == <span class="hljs-string">'['</span>)){<br><span class="hljs-built_in">solve2</span>();<br>}<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (s[<span class="hljs-number">0</span>] == <span class="hljs-string">'S'</span>){<br><span class="hljs-built_in">solve3</span>();<br>}<span class="hljs-keyword">else</span>{<br><span class="hljs-built_in">solve1</span>();<br>}<br>}<br><span class="hljs-type">int</span> cur = <span class="hljs-number">4</span>;<br><span class="hljs-keyword">while</span>(ans){<br>a[--cur] = ans % <span class="hljs-number">1024</span>;<br>ans /= <span class="hljs-number">1024</span>;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i <= <span class="hljs-number">3</span>; i++){<br><span class="hljs-keyword">if</span>(a[i]){<br>cout<<a[i]<<mp[i];<br>}<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="D最大公约数:"><a href="#D最大公约数:" class="headerlink" title="D最大公约数:"></a>D最大公约数:</h4><h5 id="暴力:"><a href="#暴力:" class="headerlink" title="暴力:"></a>暴力:</h5><ul><li>思路:有一个1就好办了,所以没有1的话就找最短的一个范围[a,b]内的数的gcd为1,需要进行b-a次出现一个1,然后就是加上n-1次,所有数都会变为1。可以过75%的点。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, a[N];<br><span class="hljs-type">int</span> ans = <span class="hljs-number">1e9</span>;<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br> cin>>n;<br> <span class="hljs-type">int</span> cnt = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br> cin>>a[i];<br> <span class="hljs-keyword">if</span>(a[i]==<span class="hljs-number">1</span>) cnt++;<br> } <br> <span class="hljs-keyword">if</span>(cnt){<br> cout<<n-cnt<<endl;<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> }<br><br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i < n; i++){<br> <span class="hljs-type">int</span> x = a[i], sum = <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = i + <span class="hljs-number">1</span>; j <= n; j++){<br> sum++;<br> x=__gcd(x,a[j]);<br> <span class="hljs-keyword">if</span>(x==<span class="hljs-number">1</span>){<br> ans = <span class="hljs-built_in">min</span>(ans, sum);<br> <span class="hljs-keyword">break</span>;<br> }<br> }<br> }<br> <br> <span class="hljs-keyword">if</span>(ans == <span class="hljs-number">1e9</span>){<br> cout<<<span class="hljs-string">"-1"</span><<endl;<br> }<span class="hljs-keyword">else</span>{<br> cout<<n<span class="hljs-number">-1</span>+ans<<endl;<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:暴力的思路并不难,抓住1这个题眼即可</li></ul><h5 id="正解:线段树-双指针:"><a href="#正解:线段树-双指针:" class="headerlink" title="正解:线段树+双指针:"></a>正解:线段树+双指针:</h5><ul><li>思路:目标是求最短区间满足其gcd为1,可以使用线段树来维护实现快速查询,利用双指针降低时间复杂度,很巧妙的结合</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span>+<span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, a[N]; <br><span class="hljs-keyword">struct</span> <span class="hljs-title class_">node</span>{<br><span class="hljs-type">int</span> l,r,g;<br>}tr[N*<span class="hljs-number">4</span>];<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">build</span><span class="hljs-params">(<span class="hljs-type">int</span> k, <span class="hljs-type">int</span> l, <span class="hljs-type">int</span> r)</span></span>{<br>tr[k].l = l, tr[k].r = r;<br><span class="hljs-keyword">if</span>(l == r){<br>tr[k].g = a[l];<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-type">int</span> mid = l + r >> <span class="hljs-number">1</span>;<br><span class="hljs-built_in">build</span>(k*<span class="hljs-number">2</span>, l, mid);<br><span class="hljs-built_in">build</span>(k*<span class="hljs-number">2</span>+<span class="hljs-number">1</span>, mid+<span class="hljs-number">1</span>, r);<br>tr[k].g = __gcd(tr[k*<span class="hljs-number">2</span>].g, tr[k*<span class="hljs-number">2</span>+<span class="hljs-number">1</span>].g);<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">search</span><span class="hljs-params">(<span class="hljs-type">int</span> k, <span class="hljs-type">int</span> l, <span class="hljs-type">int</span> r)</span></span>{<br><span class="hljs-keyword">if</span>(tr[k].l>=l && tr[k].r<=r) <span class="hljs-keyword">return</span> tr[k].g;<br><span class="hljs-type">int</span> ans = <span class="hljs-number">0</span>;<br><span class="hljs-type">int</span> mid = tr[k].l+tr[k].r>><span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(l <= mid) ans = __gcd(ans, <span class="hljs-built_in">search</span>(<span class="hljs-number">2</span>*k, l, r));<br><span class="hljs-keyword">if</span>(r > mid) ans = __gcd(ans, <span class="hljs-built_in">search</span>(<span class="hljs-number">2</span>*k+<span class="hljs-number">1</span>, l, r));<br><span class="hljs-keyword">return</span> ans;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-type">int</span> cnt = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>a[i];<br><span class="hljs-keyword">if</span>(a[i] == <span class="hljs-number">1</span>) cnt++;<br>}<br><span class="hljs-keyword">if</span>(cnt){<br>cout<<n-cnt<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br><span class="hljs-built_in">build</span>(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,n);<br><span class="hljs-type">int</span> i = <span class="hljs-number">1</span>;<br><span class="hljs-type">int</span> ans = <span class="hljs-number">1e9</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <=n; j++){<br><span class="hljs-keyword">while</span>(i<j && <span class="hljs-built_in">search</span>(<span class="hljs-number">1</span>, i+<span class="hljs-number">1</span>, j) == <span class="hljs-number">1</span>) i++;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">search</span>(<span class="hljs-number">1</span>,i,j) == <span class="hljs-number">1</span>) ans = <span class="hljs-built_in">min</span>(ans, j-i);<br>}<br><span class="hljs-keyword">if</span>(ans == <span class="hljs-number">1e9</span>) cout<<<span class="hljs-string">"-1"</span><<endl;<br><span class="hljs-keyword">else</span> cout<<n<span class="hljs-number">-1</span>+ans<<endl; <br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:线段树这部分熟悉一下还是比较好理解的,结合<strong>双指针</strong>这里还是不是特别清楚,好像是<strong>把很多不必要的情况跳过了</strong>,从而降低了时间复杂度。</li></ul><h5 id="线段树:二分:"><a href="#线段树:二分:" class="headerlink" title="线段树:二分:"></a>线段树:二分:</h5><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> inf = <span class="hljs-number">0x3f3f3f3f</span>;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N=<span class="hljs-number">100010</span>;<br><span class="hljs-type">int</span> n;<br><span class="hljs-type">int</span> a[N];<br><span class="hljs-keyword">struct</span> <span class="hljs-title class_">node</span><br>{<br> <span class="hljs-type">int</span> l, r;<br> <span class="hljs-type">int</span> g;<br>}tr[N * <span class="hljs-number">4</span>];<br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">pushup</span><span class="hljs-params">(<span class="hljs-type">int</span> u)</span></span><br><span class="hljs-function"></span>{<br> tr[u].g =__gcd(tr[u<<<span class="hljs-number">1</span>].g,tr[u<<<span class="hljs-number">1</span>|<span class="hljs-number">1</span>].g);<br>}<br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">build</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> l, <span class="hljs-type">int</span> r)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-keyword">if</span> (l == r) tr[u] = {l, r, a[r]};<br> <span class="hljs-keyword">else</span><br> {<br> tr[u] = {l, r};<br> <span class="hljs-type">int</span> mid = l + r >> <span class="hljs-number">1</span>;<br> <span class="hljs-built_in">build</span>(u << <span class="hljs-number">1</span>, l, mid), <span class="hljs-built_in">build</span>(u << <span class="hljs-number">1</span> | <span class="hljs-number">1</span>, mid + <span class="hljs-number">1</span>, r);<br> <span class="hljs-built_in">pushup</span>(u);<br> }<br>}<br><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">query</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> l, <span class="hljs-type">int</span> r)</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-keyword">if</span> (tr[u].l >= l && tr[u].r <= r) <span class="hljs-keyword">return</span> tr[u].g;<br> <span class="hljs-type">int</span> mid = tr[u].l + tr[u].r >> <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span>(r<=mid) <span class="hljs-keyword">return</span> <span class="hljs-built_in">query</span>(u<<<span class="hljs-number">1</span>,l,r);<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(l>mid) <span class="hljs-keyword">return</span> <span class="hljs-built_in">query</span>(u<<<span class="hljs-number">1</span>|<span class="hljs-number">1</span>,l,r);<br> <span class="hljs-keyword">else</span> <span class="hljs-keyword">return</span> __gcd(<span class="hljs-built_in">query</span>(u<<<span class="hljs-number">1</span>,l,r),<span class="hljs-built_in">query</span>(u<<<span class="hljs-number">1</span>|<span class="hljs-number">1</span>,l,r));<br>}<br><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br> cin>>n;<br> <span class="hljs-type">int</span> f=<span class="hljs-number">0</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">1</span>;i<=n;++i){<br> cin>>a[i];<br> <span class="hljs-keyword">if</span>(a[i]==<span class="hljs-number">1</span>) f++;<br> }<br> <span class="hljs-keyword">if</span>(f){<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,n-f);<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> } <br> <span class="hljs-built_in">build</span>(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,n);<br> <span class="hljs-keyword">if</span>(<span class="hljs-built_in">query</span>(<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,n)!=<span class="hljs-number">1</span>){<br> <span class="hljs-built_in">puts</span>(<span class="hljs-string">"-1"</span>);<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> }<br> <span class="hljs-type">int</span> ans=inf;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-number">1</span>;i<=n;++i){<br> <span class="hljs-type">int</span> l=i+<span class="hljs-number">1</span>,r=n;<br> <span class="hljs-keyword">while</span>(l<r){<br> <span class="hljs-type">int</span> mid=l+r>><span class="hljs-number">1</span>;<br> <span class="hljs-keyword">if</span>(<span class="hljs-built_in">query</span>(<span class="hljs-number">1</span>,i,mid)==<span class="hljs-number">1</span>) r=mid;<br> <span class="hljs-keyword">else</span> l=mid+<span class="hljs-number">1</span>;<br> }<br> <span class="hljs-keyword">if</span>(<span class="hljs-built_in">query</span>(<span class="hljs-number">1</span>,i,r)==<span class="hljs-number">1</span>) ans=<span class="hljs-built_in">min</span>(ans,r-i);<br> }<br> <span class="hljs-built_in">printf</span>(<span class="hljs-string">"%d\n"</span>,n<span class="hljs-number">-1</span>+ans);<br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="Eowo"><a href="#Eowo" class="headerlink" title="Eowo:"></a>Eowo:</h4><ul><li>思路:采取一种很特别的手法,随机,以最大的可能去测出结果,与字符串的操作很密切,包括find函数,random_shuffle函数</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e6</span>+<span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, ans;<br>string st[N]; <br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br>cin>>st[i];<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j < <span class="hljs-number">5e3</span>; j++ ){<br><span class="hljs-built_in">random_shuffle</span>(st, st+i+<span class="hljs-number">1</span>);<br>string t;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> k = <span class="hljs-number">0</span>; k <= i; k++){<br>t = t + st[k];<br>}<br><span class="hljs-type">int</span> res = <span class="hljs-number">0</span>;<br><span class="hljs-type">int</span> p = t.<span class="hljs-built_in">find</span>(<span class="hljs-string">"owo"</span>);<br><span class="hljs-keyword">while</span>(p != <span class="hljs-number">-1</span>){<br>res++;<br>p = t.<span class="hljs-built_in">find</span>(<span class="hljs-string">"owo"</span>, p+<span class="hljs-number">1</span>);<br>}<br>ans = <span class="hljs-built_in">max</span>(ans, res);<br>}<br>cout<<ans<<endl;<br>}<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:拓展的题目,正常暴力情况太多太复杂了</li></ul><h4 id="F环境治理:"><a href="#F环境治理:" class="headerlink" title="F环境治理:"></a>F环境治理:</h4><ul><li>思路:存在明显的二分性,对于最终的值的求解基于Floyed算法,算出每两点之间最近的距离。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">105</span>;<br><span class="hljs-type">int</span> n,q;<br><span class="hljs-type">int</span> d[N][N], limit[N][N], tmp[N][N]; <br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">cal</span><span class="hljs-params">(<span class="hljs-type">int</span> day)</span></span>{<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j < n; j++){<br>tmp[i][j] = d[i][j];<br>}<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br><span class="hljs-type">int</span> val = day/n + (day%n<span class="hljs-number">-1</span>>=i?<span class="hljs-number">1</span>:<span class="hljs-number">0</span>);<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j < n; j++){<br>tmp[i][j] = <span class="hljs-built_in">max</span>(limit[i][j], tmp[i][j]-val);<br>tmp[j][i] = <span class="hljs-built_in">max</span>(limit[j][i], tmp[j][i]-val);<br>}<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> k = <span class="hljs-number">0</span>; k < n; k++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j < n; j++){<br>tmp[i][j] = <span class="hljs-built_in">min</span>(tmp[i][k]+tmp[k][j], tmp[i][j]);<br>}<br>}<br>}<br><span class="hljs-type">int</span> res = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j < n; j++){<br>res += tmp[i][j];<br>}<br>}<br><span class="hljs-keyword">return</span> res;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>q;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j < n; j++){<br>cin>>d[i][j];<br>}<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j < n; j++){<br>cin>>limit[i][j];<br>}<br>}<br><span class="hljs-type">int</span> l = <span class="hljs-number">0</span>, r = <span class="hljs-number">1e5</span>*n, ans = <span class="hljs-number">-1</span>;<br><span class="hljs-keyword">while</span>(l < r){<br><span class="hljs-type">int</span> mid = l + r >><span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">cal</span>(mid)<=q){<br>r = mid;<br>ans = r;<br>}<span class="hljs-keyword">else</span>{<br>l = mid + <span class="hljs-number">1</span>;<br>}<br>}<br>cout<<ans<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:二分+Floyed,Floyed中k在最外层,注意细节。</li></ul><h4 id="G选素数:"><a href="#G选素数:" class="headerlink" title="G选素数:"></a>G选素数:</h4><ul><li>思路:一共两步,第一步是找m-pmax+1,设为函数f(m),在f[m]到n的范围内找到一个数i使得f[i]最小。pmax是一个数的最大质因子,可以与线性筛算法相结合,**p[prime[j]*i] = max[p[i], prime[j]]**。能与求最大质因子结合也非常的巧妙。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> MAXN=<span class="hljs-number">1000001</span>;<br><span class="hljs-type">int</span> n,t;<br><span class="hljs-type">bool</span> isprime[MAXN];<br><span class="hljs-type">int</span> prime[MAXN];<br><span class="hljs-type">int</span> p[MAXN];<br><span class="hljs-type">int</span> ans=<span class="hljs-number">1e9</span>;<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">f</span><span class="hljs-params">(<span class="hljs-type">int</span> m)</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-keyword">if</span>(isprime[m]==<span class="hljs-literal">true</span>)<br>{<br><span class="hljs-keyword">return</span> <span class="hljs-number">1e9</span>;<br>}<br><span class="hljs-keyword">return</span> (m-p[m]+<span class="hljs-number">1</span>);<br>}<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">Linear_sieve</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">2</span>; i <= n; i++){<br>isprime[i] = <span class="hljs-literal">true</span>;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">2</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(isprime[i]){<br>t++;<br>prime[t] = i;<br>p[i] = i;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= t&&prime[j]*i<=n; j++){<br>p[prime[j]*i] = <span class="hljs-built_in">max</span>(p[i], prime[j]);<br>isprime[prime[j]*i] = <span class="hljs-literal">false</span>;<br><span class="hljs-keyword">if</span>(i % prime[j] == <span class="hljs-number">0</span>){<br><span class="hljs-keyword">break</span>;<br>}<br>}<br>}<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-built_in">Linear_sieve</span>();<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i=<span class="hljs-built_in">f</span>(n);i<=n;i++)<br>{<br>ans=<span class="hljs-built_in">min</span>(ans,<span class="hljs-built_in">f</span>(i));<br>}<br><span class="hljs-keyword">if</span>(ans!=<span class="hljs-number">1e9</span>)<br>{<br>cout<<ans<<endl;<br>}<br><span class="hljs-keyword">else</span><br>{<br>cout<<<span class="hljs-string">"-1"</span><<endl;<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:需要对线性筛算法较为熟悉,算是一道数论题,倒推。或者基于所给的样例也可窥见端倪。</li></ul><h4 id="H替换字符:"><a href="#H替换字符:" class="headerlink" title="H替换字符:"></a>H替换字符:</h4><h5 id="暴力:-1"><a href="#暴力:-1" class="headerlink" title="暴力:"></a>暴力:</h5><ul><li>思路:直接模拟即可,洛谷可过60%</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span>+<span class="hljs-number">10</span>;<br>string s;<br><span class="hljs-type">int</span> m;<br><span class="hljs-type">int</span> l, r;<br><span class="hljs-type">char</span> x,y;<br><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>s;<br>cin>>m;<br><span class="hljs-keyword">while</span>(m--){<br>cin>>l>>r>>x>>y;<br>l--;r--;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = l; i <= r; i++){<br><span class="hljs-keyword">if</span>(s[i] == x){<br>s[i] = y;<br>}<br>}<br>}<br>cout<<s<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="I三角序列暴力60-:"><a href="#I三角序列暴力60-:" class="headerlink" title="I三角序列暴力60%:"></a>I三角序列暴力60%:</h4><ul><li>思路:第一反应就是二分,对于每个三角序列,进行pre操作确定它的左右边界,然后check函数先找到L,R所在的三角形的右端点,分类讨论,先基于cal,再基于cal2计算,逐步解决问题。很棒的一道模拟题。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">20</span>;<br><span class="hljs-type">int</span> n,m;<br><span class="hljs-keyword">struct</span> <span class="hljs-title class_">node</span>{<br><span class="hljs-type">int</span> len, type, l, r;<br>}a[N];<br><span class="hljs-type">int</span> pre[N];<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">cal2</span><span class="hljs-params">(<span class="hljs-type">int</span> len, <span class="hljs-type">int</span> h)</span></span>{<br><span class="hljs-type">int</span> sum = len*(len+<span class="hljs-number">1</span>)/<span class="hljs-number">2</span>;<br><span class="hljs-type">int</span> tmp = <span class="hljs-built_in">max</span>(len-h,<span class="hljs-number">0LL</span>);<br><span class="hljs-type">int</span> res = tmp*(tmp+<span class="hljs-number">1</span>)/<span class="hljs-number">2</span>;<br><span class="hljs-keyword">return</span> sum-res;<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">cal</span><span class="hljs-params">(<span class="hljs-type">int</span> idx, <span class="hljs-type">int</span> col, <span class="hljs-type">int</span> h)</span></span>{<br><span class="hljs-keyword">if</span>(col > a[idx].r) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br><span class="hljs-keyword">if</span>(a[idx].type == <span class="hljs-number">0</span>){<br><span class="hljs-keyword">return</span> <span class="hljs-built_in">cal2</span>(a[idx].len, h)-<span class="hljs-built_in">cal2</span>(col - a[idx].l, h);<br>}<span class="hljs-keyword">else</span>{<br><span class="hljs-keyword">return</span> <span class="hljs-built_in">cal2</span>(a[idx].r-col+<span class="hljs-number">1</span>, h);<br>}<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">check</span><span class="hljs-params">(<span class="hljs-type">int</span> l, <span class="hljs-type">int</span> r, <span class="hljs-type">int</span> h)</span></span>{<br><span class="hljs-type">int</span> idx_l = <span class="hljs-built_in">lower_bound</span>(pre+<span class="hljs-number">1</span>,pre+<span class="hljs-number">1</span>+n,l)-pre;<br><span class="hljs-type">int</span> idx_r = <span class="hljs-built_in">lower_bound</span>(pre+<span class="hljs-number">1</span>,pre+<span class="hljs-number">1</span>+n,r)-pre;<br><span class="hljs-keyword">if</span>(idx_l == idx_r){<br><span class="hljs-keyword">return</span> <span class="hljs-built_in">cal</span>(idx_l, l, h)-<span class="hljs-built_in">cal</span>(idx_l, r+<span class="hljs-number">1</span>, h);<br>}<br><span class="hljs-type">int</span> ans = <span class="hljs-built_in">cal</span>(idx_l, l, h) + <span class="hljs-built_in">cal</span>(idx_r, a[idx_r].l, h) - <span class="hljs-built_in">cal</span>(idx_r, r+<span class="hljs-number">1</span>, h);<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = idx_l + <span class="hljs-number">1</span>; i < idx_r; i++){<br>ans += <span class="hljs-built_in">cal</span>(i, a[i].l, h);<br>}<br><span class="hljs-keyword">return</span> ans;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m;<br><span class="hljs-type">int</span> max_h = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>a[i].len>>a[i].type;<br>max_h = <span class="hljs-built_in">max</span>(max_h, a[i].len);<br>pre[i] = pre[i<span class="hljs-number">-1</span>] + a[i].len;<br>a[i].l = pre[i<span class="hljs-number">-1</span>] + <span class="hljs-number">1</span>;<br>a[i].r = pre[i];<br>}<br><span class="hljs-type">int</span> L,R,v;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= m; i++){<br>cin>>L>>R>>v; <br><span class="hljs-type">int</span> l = <span class="hljs-number">1</span>, r = max_h + <span class="hljs-number">1</span>, h = <span class="hljs-number">-1</span>;<br><span class="hljs-keyword">while</span>(l < r){<br><span class="hljs-type">int</span> mid = l + r >><span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">check</span>(L, R, mid) >= v){<br>h = mid;<br>r = mid;<br>}<span class="hljs-keyword">else</span>{<br>l = mid + <span class="hljs-number">1</span>;<br>}<br>} <br>cout<<h<<endl;<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:遇到这种大模拟题,思路一定要清晰,划分问题然后逐步增加函数来解决。</li></ul>]]></content>
<tags>
<tag>算法</tag>
</tags>
</entry>
<entry>
<title>小白赛9</title>
<link href="/2024/04/06/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E5%B0%8F%E7%99%BD%E8%B5%9B9/"/>
<url>/2024/04/06/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E5%B0%8F%E7%99%BD%E8%B5%9B9/</url>
<content type="html"><![CDATA[<h2 id="补题和反思做题状态是最最最最重要的"><a href="#补题和反思做题状态是最最最最重要的" class="headerlink" title="补题和反思做题状态是最最最最重要的"></a>补题和反思做题状态是最最最最重要的</h2><h4 id="字符迁移:"><a href="#字符迁移:" class="headerlink" title="字符迁移:"></a>字符迁移:</h4><ul><li>只能写出暴力算法,待补</li><li>补题:实际上就是<strong>差分数组</strong>的模板题,cha[i] = a[i] - a[i-1], 相当于原数组就是差分数组的前缀和。</li></ul><h4 id="字典树考试:"><a href="#字典树考试:" class="headerlink" title="字典树考试:"></a>字典树考试:</h4><ul><li>通过,数学题</li></ul><h4 id="无理数位数查询:"><a href="#无理数位数查询:" class="headerlink" title="无理数位数查询:"></a>无理数位数查询:</h4><ul><li>复杂的模拟题,没有想好就开始写了,边写边改思路,代码也很混乱,导致浪费了很多时间,最后脑子越来越乱,还是没有做出来。<strong>这一点要想想办法怎么避免和警惕?</strong></li><li>花了近三天的时间,在正确思路的基础上,自己可以写出过60%的代码,已经很不错了</li><li>总结:<ul><li>类型:是那种比较复杂的模拟题,对于正常的用例,可以编写出正确代码,但是有很多的边界情况,特殊情况需要考虑,需要自己编写多个函数实现。代码越长,越容易出错。</li></ul></li></ul><h4 id="盖印章:"><a href="#盖印章:" class="headerlink" title="盖印章:"></a>盖印章:</h4><ul><li>后半段时间才能做,比较简单,最后一段时间通过了。相当于正式赛中排在后面但难度没那么高的题目。</li></ul><h4 id="贝贝的集合:"><a href="#贝贝的集合:" class="headerlink" title="贝贝的集合:"></a>贝贝的集合:</h4><ul><li>来不及看,只知道难度比较高</li></ul><h4 id="总结:"><a href="#总结:" class="headerlink" title="总结:"></a>总结:</h4><ul><li><p>0.比赛<strong>刚开始的时候就要冷静,不急这一两分钟</strong>,后面时间还很多,前几道简单的题目可以做慢一点,做对最重要</p></li><li><p>1.首要目标是尽可能的涵盖各种可以想到的情况,<strong>一定要把算法的流程理清楚再编写代码</strong>,可以大大节省后续的时间</p></li><li><p>2.可以提前<strong>准备好专门的测试程序</strong>,来进行<strong>单个函数的测试</strong>或者<strong>预定义输入对整个代码进行测试</strong>,反复修改代码也不是一个好的选择,能过部分情况的代码要进行保留</p></li><li><p>3.<strong>控制在一道题上的时间,一般30分钟左右为佳</strong>,时间一旦长,思路就会变得很狭窄,可以看看其他题目来换换环境</p></li><li><p>4.可以留出至少40分钟的时间,<strong>把最后的时间更多放在检查上面</strong>,再重新看看题目,反复测试能得到的部分分,不要一直死磕某一道题。测试尽可能想出多的情况,丰富于题目所给的样例。</p></li></ul>]]></content>
<tags>
<tag>蓝桥杯</tag>
</tags>
</entry>
<entry>
<title>蓝桥杯专题整理</title>
<link href="/2024/04/04/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E4%B8%93%E9%A2%98%E6%95%B4%E7%90%86/"/>
<url>/2024/04/04/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E4%B8%93%E9%A2%98%E6%95%B4%E7%90%86/</url>
<content type="html"><![CDATA[<h3 id="1-二分"><a href="#1-二分" class="headerlink" title="1.二分:"></a>1.二分:</h3><ul><li>描述:可以有效降低时间复杂度为NlogN, 大多情况下前提是找最大值的最小值或最小值的最大值,即<strong>在一个区间内有一部分是满足条件的,另一部分不满足,找两个部分交界的那个点</strong>。</li><li>写法:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-type">int</span> l = , r = ;<br><span class="hljs-keyword">while</span>(l < r){<br><span class="hljs-type">int</span> mid = (l + r)>><span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">check</span>(mid)) r = mid;<br><span class="hljs-keyword">else</span> l = mid + <span class="hljs-number">1</span>;<br>}<br><span class="hljs-comment">//或者</span><br><span class="hljs-type">int</span> l = , r = ;<br><span class="hljs-keyword">while</span>(l < r){<br><span class="hljs-type">int</span> mid = (l + r + <span class="hljs-number">1</span>)>><span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">check</span>(mid)) l =mid;<br><span class="hljs-keyword">else</span> r = mid - <span class="hljs-number">1</span>;<br>}<br><span class="hljs-comment">//结果均为l或r,此时两者相等。最后可以再double check一下是否有解</span><br></code></pre></td></tr></table></figure><h4 id="例题:"><a href="#例题:" class="headerlink" title="例题:"></a>例题:</h4><h5 id="子串简写"><a href="#子串简写" class="headerlink" title="子串简写"></a>子串简写</h5><ul><li><p>在数组上找两个给定的值的组合,有先后之分,两者距离有要求,那么可以固定后值,二分所有前值,vector很好用,相对于数组可以不用新增一个记录下标的变量。</p></li><li><p>注意:两个给定的值可能相等,特殊情况要考虑进来</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">5e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> k;<br>string s;<br><span class="hljs-type">char</span> c1, c2;<br>vector<<span class="hljs-type">int</span>> pos;<br><span class="hljs-type">int</span> ans;<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>k;<br>cin>>s>>c1>>c2;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < s.<span class="hljs-built_in">length</span>(); i++){<br><span class="hljs-keyword">if</span>(s[i] == c1){<br>pos.<span class="hljs-built_in">push_back</span>(i);<br>}<br><span class="hljs-keyword">if</span>(s[i] == c2){<br><span class="hljs-keyword">if</span>(pos.<span class="hljs-built_in">size</span>() == <span class="hljs-number">0</span> || i - pos[<span class="hljs-number">0</span>] + <span class="hljs-number">1</span> < k) <span class="hljs-keyword">continue</span>;<br><span class="hljs-type">int</span> l = <span class="hljs-number">0</span>, r = pos.<span class="hljs-built_in">size</span>() - <span class="hljs-number">1</span>;<br><span class="hljs-keyword">while</span>(l < r){<br><span class="hljs-type">int</span> mid = (l + r + <span class="hljs-number">1</span>)>><span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(i - pos[mid] + <span class="hljs-number">1</span> >= k) l = mid;<br><span class="hljs-keyword">else</span> r = mid - <span class="hljs-number">1</span>;<br>}<br>ans += l + <span class="hljs-number">1</span>;<br>}<br>}<br>cout<<ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h5 id="青蛙过河"><a href="#青蛙过河" class="headerlink" title="青蛙过河"></a>青蛙过河</h5><h3 id="2-优先队列"><a href="#2-优先队列" class="headerlink" title="2.优先队列"></a>2.优先队列</h3><ul><li>描述:通过大根堆或小根堆可以以NLogN的速度找到数组中的最值,从而降低时间复杂度</li><li>写法:</li></ul><figure class="highlight cpp"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs cpp"><span class="hljs-comment">//小根堆:</span><br>priority_queue<pii, vector<pii>, greater<pii>> q;<br>priority_queue <<span class="hljs-type">int</span>,vector<<span class="hljs-type">int</span>>,greater<<span class="hljs-type">int</span>> > q;<br><span class="hljs-comment">//大根堆(默认):</span><br>priority_queue<pii, vector<pii>> q;<br>priority_queue <<span class="hljs-type">int</span>,vector<<span class="hljs-type">int</span>>> q;<br></code></pre></td></tr></table></figure><h4 id="例题:-1"><a href="#例题:-1" class="headerlink" title="例题:"></a>例题:</h4><h5 id="整数删除"><a href="#整数删除" class="headerlink" title="整数删除"></a>整数删除</h5><ul><li>找最小值删除同时给它的相邻数加上这个最小值的值。关键在于快速找<strong>最小值及其位置</strong>还有它<strong>相邻的值的位置</strong>。前者通过<strong>小根堆</strong>解决,后者通过双向队列解决。</li><li>注意:双向队列的写法,增加一个下标为-1的点,使之变成一个环,方便边界的处理。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">5e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-keyword">typedef</span> pair<<span class="hljs-type">int</span> ,<span class="hljs-type">int</span>> pii; <br><span class="hljs-type">int</span> n, k, a[N], st[N];<br><span class="hljs-type">int</span> l[N], r[N];<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>k;<br>priority_queue<pii, vector<pii>, greater<pii>> q;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br>cin>>a[i];<br>q.<span class="hljs-built_in">push</span>({a[i], i});<br>st[i] = a[i];<br>l[i] = i - <span class="hljs-number">1</span>;<br>r[i] = i + <span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(i == n<span class="hljs-number">-1</span>) r[i] = <span class="hljs-number">-1</span>;<br>} <br><span class="hljs-keyword">while</span>(k){<br>pii i = q.<span class="hljs-built_in">top</span>();<br>q.<span class="hljs-built_in">pop</span>();<br><span class="hljs-keyword">if</span>(i.first != st[i.second]){<br>q.<span class="hljs-built_in">push</span>({st[i.second], i.second});<br><span class="hljs-keyword">continue</span>;<br>}<br>k--;<br><span class="hljs-type">int</span> x = i.second, y = i.first;<br><span class="hljs-keyword">if</span>(l[x] >= <span class="hljs-number">0</span>) st[l[x]] += y;<br><span class="hljs-keyword">if</span>(r[x] >= <span class="hljs-number">0</span>) st[r[x]] += y;<br><br><span class="hljs-keyword">if</span>(l[x] >= <span class="hljs-number">0</span>) r[l[x]] = r[x];<br><span class="hljs-keyword">if</span>(r[x] >= <span class="hljs-number">0</span>) l[r[x]] = l[x];<br>st[x] = <span class="hljs-number">-1</span>;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br><span class="hljs-keyword">if</span>(st[i] >= <span class="hljs-number">0</span>){<br>cout<<st[i]<<<span class="hljs-string">" "</span>;<br>}<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h3 id="3-dfs暴力"><a href="#3-dfs暴力" class="headerlink" title="3.dfs暴力"></a>3.dfs暴力</h3><ul><li>描述:对<strong>问题解决过程进行有逻辑的分析</strong>,使得可以通过dfs<strong>模拟所有的情况</strong>,来得出最终的答案,过程中可以通过剪枝来降低时间复杂度。</li><li><strong>1.判断是否存在可行方案</strong>,一般有两种写法,一是dfs返回类型为bool,一旦有一种,就一层层返回true,每一次dfs都要进行判断;二是设置一个flag变量,dfs返回类型为void,注意也要实时判断,<strong>一旦为1就可以直接返回了</strong>。</li></ul><h4 id="例题:-2"><a href="#例题:-2" class="headerlink" title="例题:"></a>例题:</h4><h5 id="飞机降落:"><a href="#飞机降落:" class="headerlink" title="飞机降落:"></a>飞机降落:</h5><ul><li>n最大为10,可以模拟所有的情况来判断结果。没有合适的贪心算法。是一道比较模板的dfs遍历</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> time)</span></span>{ <span class="hljs-comment">//dfs无返回值</span><br><span class="hljs-keyword">if</span>(u == n){<br>flag = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(flag == <span class="hljs-number">1</span>) <span class="hljs-keyword">return</span>;<br><span class="hljs-keyword">if</span>(st[i] == <span class="hljs-number">1</span>) <span class="hljs-keyword">continue</span>;<br><span class="hljs-keyword">if</span>(time > pl[i].latest){<br>flag = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">return</span>;<br>}<br>st[i] = <span class="hljs-number">1</span>;<br><span class="hljs-built_in">dfs</span>(u + <span class="hljs-number">1</span>, <span class="hljs-built_in">max</span>(time, pl[i].t) + pl[i].l);<br>st[i] = <span class="hljs-number">0</span>;<br>} <br>}<br></code></pre></td></tr></table></figure><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-function"><span class="hljs-type">bool</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> time)</span></span>{ <span class="hljs-comment">//dfs返回值为bool类型</span><br><span class="hljs-keyword">if</span>(u == n){<br><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(st[i] == <span class="hljs-number">1</span>) <span class="hljs-keyword">continue</span>;<br><span class="hljs-keyword">if</span>(time > pl[i].latest){<br><span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>}<br>st[i] = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">dfs</span>(u + <span class="hljs-number">1</span>, <span class="hljs-built_in">max</span>(time, pl[i].t) + pl[i].l)){<br><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>}<br>st[i] = <span class="hljs-number">0</span>;<br>} <br>}<br></code></pre></td></tr></table></figure><h5 id="买瓜:"><a href="#买瓜:" class="headerlink" title="买瓜:"></a>买瓜:</h5><ul><li>每个瓜都有三种状态(不选,选,切半选),选取若干个,满足重量和为m。dfs三种状态+剪枝提前退出。可以获得一半分数。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">35</span>;<br><span class="hljs-type">int</span> n, m, a[N];<br><span class="hljs-type">int</span> ans = N;<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> sum, <span class="hljs-type">int</span> cnt)</span></span>{<br><span class="hljs-keyword">if</span>(u == n){<br><span class="hljs-keyword">if</span>(sum == m) ans = <span class="hljs-built_in">min</span>(ans, cnt);<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-keyword">if</span>(sum > m) <span class="hljs-keyword">return</span>;<br><span class="hljs-keyword">if</span>(sum + a[u] <= m) <span class="hljs-built_in">dfs</span>(u + <span class="hljs-number">1</span>, sum + a[u], cnt);<br><span class="hljs-keyword">if</span>(sum + a[u]/<span class="hljs-number">2</span> <= m) <span class="hljs-built_in">dfs</span>(u + <span class="hljs-number">1</span>, sum + a[u]/<span class="hljs-number">2</span>, cnt + <span class="hljs-number">1</span>);<br><span class="hljs-built_in">dfs</span>(u + <span class="hljs-number">1</span>, sum, cnt);<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m;<br>m *= <span class="hljs-number">2</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br>cin>>a[i];<br>a[i] *= <span class="hljs-number">2</span>;<br>}<br><span class="hljs-built_in">sort</span>(a, a + n);<br><span class="hljs-built_in">dfs</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);<br><span class="hljs-keyword">if</span>(ans == N) cout<<<span class="hljs-string">"-1"</span><<endl;<br><span class="hljs-keyword">else</span> cout<<ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h5 id="颜色平衡树:"><a href="#颜色平衡树:" class="headerlink" title="颜色平衡树:"></a>颜色平衡树:</h5><ul><li>树上的dfs,涉及自底向上的更新,思路清晰后写起来并不难。调试时发现没有结果,原因是dfs(i),应该是dfs(son(u)(i)),要注意到这些细节。可以过60%的数据。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">2e5</span>;<br><span class="hljs-type">int</span> n, col[N], ans;<br>vector<<span class="hljs-type">int</span>> son[N]; <br>unordered_map<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> mp[N];<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> u)</span></span>{<br><span class="hljs-keyword">if</span>(son[u].<span class="hljs-built_in">size</span>() == <span class="hljs-number">0</span>){<br>ans++;<br>mp[u][col[u]]++;<br><span class="hljs-keyword">return</span>;<br>}<br>mp[u][col[u]]++;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < son[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-built_in">dfs</span>(son[u][i]);<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-keyword">auto</span> i: son[u]){<br><span class="hljs-keyword">for</span>(<span class="hljs-keyword">auto</span> it:mp[i]){<br><span class="hljs-type">int</span> x = it.first, y = it.second;<br>mp[u][x] += y;<br>}<br>}<br><span class="hljs-type">int</span> tmp = <span class="hljs-number">0</span>, flag = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-keyword">auto</span> i:mp[u]){<br><span class="hljs-keyword">if</span>(!tmp) tmp = i.second;<br><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(i.second != tmp){<br>flag = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">break</span>;<br>}<br>}<br><span class="hljs-keyword">if</span>(flag) ans++;<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>, f; i <= n; i++){<br>cin>>col[i]>>f;<br>son[f].<span class="hljs-built_in">push_back</span>(i);<br>}<br><span class="hljs-built_in">dfs</span>(<span class="hljs-number">1</span>);<br>cout<<ans<<endl; <br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h5 id="景区导游:"><a href="#景区导游:" class="headerlink" title="景区导游:"></a>景区导游:</h5><ul><li>dfs暴力树上两点的距离,dfs返回值为int,注意及时判断return。可以过30%。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-keyword">typedef</span> pair<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> PII;<br><span class="hljs-type">int</span> n, k, a[N];<br>vector<PII> e[N];<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> fa, <span class="hljs-type">int</span> end, <span class="hljs-type">int</span> sum)</span></span>{<br><span class="hljs-keyword">if</span>(u == end){<br><span class="hljs-keyword">return</span> sum;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> x = e[u][i].first, y = e[u][i].second;<br><span class="hljs-keyword">if</span>(x == fa) <span class="hljs-keyword">continue</span>;<br><span class="hljs-type">int</span> tmp = <span class="hljs-built_in">dfs</span>(x, u, end, sum + y);<br><span class="hljs-keyword">if</span>(tmp) <span class="hljs-keyword">return</span> tmp;<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>k;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>,u,v,t; i < n; i++){<br>cin>>u>>v>>t;<br>e[u].<span class="hljs-built_in">push_back</span>({v, t});<br>e[v].<span class="hljs-built_in">push_back</span>({u, t});<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= k; i++){<br>cin>>a[i];<br>}<br><span class="hljs-type">int</span> sum = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">2</span>; i <= k; i++){<br>sum += <span class="hljs-built_in">dfs</span>(a[i<span class="hljs-number">-1</span>], <span class="hljs-number">-1</span>, a[i], <span class="hljs-number">0</span>);<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= k; i++){<br><span class="hljs-keyword">if</span>(i == <span class="hljs-number">1</span>){<br>cout<<sum - <span class="hljs-built_in">dfs</span>(a[<span class="hljs-number">1</span>], <span class="hljs-number">-1</span>, a[<span class="hljs-number">2</span>], <span class="hljs-number">0</span>)<<<span class="hljs-string">" "</span>;<br>}<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(i == k){<br>cout<<sum - <span class="hljs-built_in">dfs</span>(a[k<span class="hljs-number">-1</span>], <span class="hljs-number">-1</span>, a[k], <span class="hljs-number">0</span>)<<<span class="hljs-string">" "</span>;<br>}<span class="hljs-keyword">else</span>{<br>cout<<sum-<span class="hljs-built_in">dfs</span>(a[i<span class="hljs-number">-1</span>], <span class="hljs-number">-1</span>, a[i], <span class="hljs-number">0</span>)-<span class="hljs-built_in">dfs</span>(a[i], <span class="hljs-number">-1</span>, a[i+<span class="hljs-number">1</span>], <span class="hljs-number">0</span>)+<span class="hljs-built_in">dfs</span>(a[i<span class="hljs-number">-1</span>], <span class="hljs-number">-1</span>, a[i+<span class="hljs-number">1</span>], <span class="hljs-number">0</span>)<<<span class="hljs-string">" "</span>;<br>}<br>}<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h5 id="砍树:"><a href="#砍树:" class="headerlink" title="砍树:"></a>砍树:</h5><ul><li>模拟从树上一个点到另一个点的过程,这个线路上的边+1,最终权重为m的序号最大的边为答案,涉及边的存储,用map来实现两个点对应一条边的序号</li><li>dfs采用bool返回值,只有在线路上的边可以+1</li></ul><figure class="highlight arduino"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br></pre></td><td class="code"><pre><code class="hljs arduino"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-keyword">typedef</span> pair<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> PII;<br><span class="hljs-type">int</span> n, m;<br>vector<<span class="hljs-type">int</span>> e[N];<br><span class="hljs-type">int</span> w[N];<br>map<PII ,<span class="hljs-type">int</span>> id; <br><span class="hljs-function"><span class="hljs-type">bool</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> fa, <span class="hljs-type">int</span> end)</span></span>{<br><span class="hljs-keyword">if</span>(u == end){<br><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> s = e[u][i];<br><span class="hljs-keyword">if</span>(s == fa) <span class="hljs-keyword">continue</span>;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">dfs</span>(s, u, end)){<br><span class="hljs-type">int</span> ID = id[{s, u}];<br>w[ID]++;<br><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>}<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>,u,v; i <= n<span class="hljs-number">-1</span>; i++){<br>cin>>u>>v;<br>e[u].<span class="hljs-built_in">push_back</span>(v);<br>e[v].<span class="hljs-built_in">push_back</span>(u);<br>id[{u,v}] = i;<br>id[{v,u}] = i;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>,a,b; i <= m; i++){<br>cin>>a>>b;<br><span class="hljs-built_in">dfs</span>(a, <span class="hljs-number">-1</span>, b);<br>}<br><span class="hljs-type">int</span> ans = <span class="hljs-number">-1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = n<span class="hljs-number">-1</span>; i >= <span class="hljs-number">1</span>; i--){<br><span class="hljs-keyword">if</span>(w[i] == m){<br>ans = i;<br><span class="hljs-keyword">break</span>;<br>}<br>}<br>cout<<ans<<endl;<br><br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h3 id="4-dp"><a href="#4-dp" class="headerlink" title="4.dp"></a>4.dp</h3><ul><li>描述:针对子问题与整个问题关联,并求最优解的题目,大多情况下可以dfs来暴力求解</li></ul><h4 id="例题:-3"><a href="#例题:-3" class="headerlink" title="例题:"></a>例题:</h4><h5 id="接龙序列:"><a href="#接龙序列:" class="headerlink" title="接龙序列:"></a>接龙序列:</h5><h6 id="解法一:数字dp"><a href="#解法一:数字dp" class="headerlink" title="解法一:数字dp"></a>解法一:数字dp</h6><ul><li>超级巧妙的把结尾的数字作为dp[i]的含义,dp[i]表示以i为结尾的最长接龙子序列的长度,从左往右遍历一遍即可。把数字当作字符串来看可以很方便地得到第一位和最后一位。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n;<br><span class="hljs-type">int</span> dp[<span class="hljs-number">15</span>];<br>string s;<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>s;<br><span class="hljs-type">int</span> m = s.<span class="hljs-built_in">length</span>();<br>dp[s[m<span class="hljs-number">-1</span>] - <span class="hljs-string">'0'</span>] = <span class="hljs-built_in">max</span>(dp[s[m<span class="hljs-number">-1</span>] - <span class="hljs-string">'0'</span>], dp[s[<span class="hljs-number">0</span>] - <span class="hljs-string">'0'</span>] + <span class="hljs-number">1</span>);<br>}<br><span class="hljs-type">int</span> ans = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i <= <span class="hljs-number">9</span>; i++){<br>ans = <span class="hljs-built_in">max</span>(ans, dp[i]);<br>}<br>cout<<n -ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h6 id="解法二:dfs暴力"><a href="#解法二:dfs暴力" class="headerlink" title="解法二:dfs暴力"></a>解法二:dfs暴力</h6><ul><li>每个数字无非就是选和不选两种情况。<strong>ans和最后的结果cnt比较</strong>,过程可以增加一些剪枝,可以过23%。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, a[N];<br><span class="hljs-type">int</span> ans;<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">getFirst</span><span class="hljs-params">(<span class="hljs-type">int</span> x)</span></span>{<br><span class="hljs-keyword">while</span>(x > <span class="hljs-number">9</span>){<br>x /= <span class="hljs-number">10</span>;<br>}<br><span class="hljs-keyword">return</span> x;<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">getLast</span><span class="hljs-params">(<span class="hljs-type">int</span> x)</span></span>{<br><span class="hljs-keyword">return</span> x % <span class="hljs-number">10</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> cnt, <span class="hljs-type">int</span> last)</span></span>{<br><span class="hljs-keyword">if</span>(u == n + <span class="hljs-number">1</span>){<br>ans = <span class="hljs-built_in">max</span>(ans, cnt);<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-keyword">if</span>(n - u + cnt < ans) <span class="hljs-keyword">return</span>;<br><span class="hljs-keyword">if</span>(last == <span class="hljs-number">-1</span> || last == <span class="hljs-built_in">getFirst</span>(a[u])){<br><span class="hljs-built_in">dfs</span>(u + <span class="hljs-number">1</span>, cnt + <span class="hljs-number">1</span>, <span class="hljs-built_in">getLast</span>(a[u]));<br>}<br><span class="hljs-built_in">dfs</span>(u + <span class="hljs-number">1</span>, cnt, last);<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>a[i];<br>}<br><span class="hljs-built_in">dfs</span>(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">-1</span>);<br>cout<<n - ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h6 id="解法三:基于解法二的二维dp"><a href="#解法三:基于解法二的二维dp" class="headerlink" title="解法三:基于解法二的二维dp"></a>解法三:基于解法二的二维dp</h6><ul><li>还是选或不选两种,dp(i)(j)表示到第i个数为止,下标为j的最长接龙数列的长度。不选的话,直接把dp(i-1)(j)复制过来就可以了。</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, a[N], ans;<br><span class="hljs-type">int</span> dp[N][<span class="hljs-number">15</span>];<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">getFirst</span><span class="hljs-params">(<span class="hljs-type">int</span> x)</span></span>{<br><span class="hljs-keyword">while</span>(x > <span class="hljs-number">9</span>){<br>x /= <span class="hljs-number">10</span>;<br>}<br><span class="hljs-keyword">return</span> x;<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">getLast</span><span class="hljs-params">(<span class="hljs-type">int</span> x)</span></span>{<br><span class="hljs-keyword">return</span> x % <span class="hljs-number">10</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>a[i]; <br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j < <span class="hljs-number">10</span>; j++){<br>dp[i][j] = dp[i<span class="hljs-number">-1</span>][j];<br>}<br><span class="hljs-type">int</span> last = <span class="hljs-built_in">getLast</span>(a[i]);<br><span class="hljs-type">int</span> first = <span class="hljs-built_in">getFirst</span>(a[i]);<br>dp[i][last] = <span class="hljs-built_in">max</span>(dp[i][last], dp[i<span class="hljs-number">-1</span>][first] + <span class="hljs-number">1</span>);<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-number">10</span>; i++){<br>ans = <span class="hljs-built_in">max</span>(ans, dp[n][i]);<br>}<br>cout<<n - ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><p>5.最短路径</p><h5 id="网络稳定性:"><a href="#网络稳定性:" class="headerlink" title="网络稳定性:"></a>网络稳定性:</h5><ul><li>采用Floyd算法进行暴力</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-type">int</span> dp[<span class="hljs-number">5005</span>][<span class="hljs-number">5005</span>]; <br><span class="hljs-type">int</span> n, m, q;<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-built_in">memset</span>(dp,<span class="hljs-number">-1</span>,<span class="hljs-built_in">sizeof</span>(dp));<br>cin>>n>>m>>q;<br><span class="hljs-type">int</span> u,v,x;<br><span class="hljs-keyword">while</span>(m--){<br>cin>>u>>v>>x;<br>dp[u][v] = <span class="hljs-built_in">max</span>(dp[u][v], x);<br>dp[v][u] = <span class="hljs-built_in">max</span>(dp[v][u], x);<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> k = <span class="hljs-number">1</span>; k <= n; k++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n ;i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br><span class="hljs-keyword">if</span>(i != j && i != k && j != k){<br>dp[i][j] = <span class="hljs-built_in">max</span>(dp[i][j], <span class="hljs-built_in">min</span>(dp[i][k],dp[k][j]));<br>}<br>}<br>}<br>}<br><span class="hljs-keyword">while</span>(q--){<br>cin>>u>>v;<br>cout<<dp[u][v]<<endl;<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>蓝桥杯</tag>
</tags>
</entry>
<entry>
<title>蓝桥杯模拟赛练习</title>
<link href="/2024/03/31/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E6%A8%A1%E6%8B%9F%E8%B5%9B%E7%BB%83%E4%B9%A0/"/>
<url>/2024/03/31/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E6%A8%A1%E6%8B%9F%E8%B5%9B%E7%BB%83%E4%B9%A0/</url>
<content type="html"><![CDATA[<h2 id="第8场小白赛:"><a href="#第8场小白赛:" class="headerlink" title="第8场小白赛:"></a>第8场小白赛:</h2><h4 id="二进制王国:"><a href="#二进制王国:" class="headerlink" title="二进制王国:"></a>二进制王国:</h4><ul><li><p>主要是<strong>自定义排序</strong>,这个cmp的写法要熟悉,用到的地方还是有的。</p></li><li><p><strong>int cmp(const string &s1, const string &s2){</strong><br><strong>return s1 + s2 < s2 + s1;</strong><br><strong>}</strong></p></li><li><p>代码:</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">2e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n;<br>string s[N];<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">cmp</span><span class="hljs-params">(<span class="hljs-type">const</span> string &s1, <span class="hljs-type">const</span> string &s2)</span></span>{<br><span class="hljs-keyword">return</span> s1 + s2 < s2 + s1;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br>cin>>s[i];<br>}<br><span class="hljs-built_in">sort</span>(s, s + n, cmp);<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br>cout<<s[i];<br>}<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><h4 id="djwcb:"><a href="#djwcb:" class="headerlink" title="djwcb:"></a>djwcb:</h4><ul><li>找规律题目,0-9的幂的个位数存在循环的规律,那么问题就变为一个超大的数p%一个个位数,可以从左开始逐位mod,结果乘10累计到下一位。很不错的一道思维题。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> a[] = {<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">4</span>,<span class="hljs-number">4</span>,<span class="hljs-number">2</span>,<span class="hljs-number">1</span>,<span class="hljs-number">1</span>,<span class="hljs-number">4</span>,<span class="hljs-number">4</span>,<span class="hljs-number">2</span>};<br><span class="hljs-type">int</span> t,n;<br>string p;<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">solve</span><span class="hljs-params">()</span></span>{<br>cin>>n>>p;<br>n = n % <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> m = a[n];<br><span class="hljs-type">int</span> tmp = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < p.<span class="hljs-built_in">size</span>(); i++){<br>tmp = (tmp*<span class="hljs-number">10</span> + p[i]-<span class="hljs-string">'0'</span>) % m;<br>}<br><span class="hljs-keyword">if</span>(m == <span class="hljs-number">1</span>){<br>cout<<n<<endl;<br>}<span class="hljs-keyword">else</span>{<br><span class="hljs-keyword">if</span>(tmp == <span class="hljs-number">0</span>) tmp = a[n];<br>cout<<(<span class="hljs-type">int</span>)<span class="hljs-built_in">pow</span>(n, tmp)%<span class="hljs-number">10</span><<endl;<br>}<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>t;<br><span class="hljs-keyword">while</span>(t--){<br><span class="hljs-built_in">solve</span>();<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure>]]></content>
<tags>
<tag>蓝桥杯</tag>
</tags>
</entry>
<entry>
<title>重做蓝桥杯真题2023年省赛A组</title>
<link href="/2024/03/31/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E9%87%8D%E5%81%9A%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%9F%E9%A2%98/"/>
<url>/2024/03/31/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E9%87%8D%E5%81%9A%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%9F%E9%A2%98/</url>
<content type="html"><![CDATA[<h4 id="A幸运数:"><a href="#A幸运数:" class="headerlink" title="A幸运数:"></a>A幸运数:</h4><ul><li>直接模拟,顺利通过</li></ul><h4 id="B有奖问答:"><a href="#B有奖问答:" class="headerlink" title="B有奖问答:"></a>B有奖问答:</h4><ul><li>使用dfs来进行较大规模的模拟,刚开始几次没有弄清题意,答案错了几次,最终答对了。在比赛时不会有验证答案的机会,所以更要加倍的小心理解题意,<strong>多次验证和检查</strong>。</li></ul><h4 id="C平方数:"><a href="#C平方数:" class="headerlink" title="C平方数:"></a>C平方数:</h4><ul><li>通过数学和手动打表找规律可以找到解体思路,最后写代码时笔误了写错导致前两次未通过。比赛时要注意尽量<strong>多搞几组数据进行测试再提交</strong>,甚至可以通过暴力编写测试程序来对拍。</li></ul><h4 id="D更小的数:"><a href="#D更小的数:" class="headerlink" title="D更小的数:"></a>D更小的数:</h4><ul><li>先是模拟,再然后尝试dp,推导归类它的求解过程,最终做出来了!关键在于耐心,大胆假设,小心求证。还有就是dp的一般套路。</li></ul><h4 id="E颜色平衡树:"><a href="#E颜色平衡树:" class="headerlink" title="E颜色平衡树:"></a>E颜色平衡树:</h4><ul><li>没有做出来,只有一些感觉,搜了一下发现一篇很厉害的题解,就是树上dfs,涉及的stl也不复杂,却过了97%的数据,值得反复学习。</li><li>研究了这个97%的暴力做法,发现很反直觉,但是也发现自己其实是可以写出来暴力的写法的,只不过通过数据点少些。能写出来暴力做法就很棒了!</li></ul><h4 id="F买瓜:"><a href="#F买瓜:" class="headerlink" title="F买瓜:"></a>F买瓜:</h4><ul><li>尝试了dfs分析暴力并优化,过了50%,很不错!</li></ul><h4 id="G网络连通性:"><a href="#G网络连通性:" class="headerlink" title="G网络连通性:"></a>G网络连通性:</h4><ul><li>基本可以写出来暴力的算法,但是忽略了一些特殊情况,导致没有得分,一个是输入的多条数据可能会重合,需要更新,一个是两个点之间可以没有直接相连的线,也可以更新。特殊情况一定要反复考虑到,尤其是本以为是优化的更加反复检验。有时间的话可以构造数据来测试。</li></ul>]]></content>
</entry>
<entry>
<title>蓝桥杯2023年省赛真题分析</title>
<link href="/2024/03/11/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF2023%E5%B9%B4%E7%9C%81%E8%B5%9B%E6%80%BB%E7%BB%93/"/>
<url>/2024/03/11/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF2023%E5%B9%B4%E7%9C%81%E8%B5%9B%E6%80%BB%E7%BB%93/</url>
<content type="html"><![CDATA[<h2 id="2023年蓝桥杯真题分析"><a href="#2023年蓝桥杯真题分析" class="headerlink" title="2023年蓝桥杯真题分析"></a>2023年蓝桥杯真题分析</h2><h4 id="A幸运数"><a href="#A幸运数" class="headerlink" title="A幸运数"></a>A幸运数</h4><ul><li>模拟题,比较简单,细心一点就可以得分</li></ul><h4 id="B有奖问答"><a href="#B有奖问答" class="headerlink" title="B有奖问答"></a>B有奖问答</h4><ul><li>dfs或者简单dp,也是比较容易的题,要冷静分析,dfs相对来说更清晰一些</li></ul><h4 id="C平方差"><a href="#C平方差" class="headerlink" title="C平方差"></a>C平方差</h4><ul><li>找规律的题目,比较简单,是可以做出来的</li></ul><h4 id="D更小的数"><a href="#D更小的数" class="headerlink" title="D更小的数"></a>D更小的数</h4><ul><li>区间dp,思路不难,但是要对基本dp问题足够熟练</li></ul><h4 id="H异或和之和"><a href="#H异或和之和" class="headerlink" title="H异或和之和"></a>H异或和之和</h4><ul><li>位运算,联系前缀和,没有经验不太好做出来</li></ul><h4 id="总结:"><a href="#总结:" class="headerlink" title="总结:"></a><strong>总结</strong>:</h4><p>以上的题目是能力之内可以尝试做出来的,或者拿大部分的分,也是学习的重点。所以接下来的学习除了刷真题还要包括<strong>dfs</strong>和<strong>简单经典的dp</strong>还有一些<strong>经典题目</strong>。</p><ul><li>剩余题目思考是否有暴力解决得部分分的方法,知道考察什么知识点</li></ul>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>蓝桥杯</tag>
</tags>
</entry>
<entry>
<title>蓝桥杯真题训练-2023年省赛B组</title>
<link href="/2024/03/11/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%9F%E9%A2%98%E8%AE%AD%E7%BB%83-2023%E5%B9%B4%E7%9C%81%E8%B5%9BB%E7%BB%84/"/>
<url>/2024/03/11/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%9F%E9%A2%98%E8%AE%AD%E7%BB%83-2023%E5%B9%B4%E7%9C%81%E8%B5%9BB%E7%BB%84/</url>
<content type="html"><![CDATA[<h2 id="2023年省赛题目B组"><a href="#2023年省赛题目B组" class="headerlink" title="2023年省赛题目B组"></a>2023年省赛题目B组</h2><h3 id="炼冶金属:"><a href="#炼冶金属:" class="headerlink" title="炼冶金属:"></a>炼冶金属:</h3><ul><li><p>描述:根据这 <em>N</em> 条冶炼记录,请你推测出转换率 <em>V</em> 的最小值和最大值分别可能是多少,题目保证评测数据不存在无解的情况。</p></li><li><p>思路:根据情况很顺利地推导出逻辑,代码实现即可</p></li><li><p>代码:</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> INF = <span class="hljs-number">0x7fffffff</span>;<br><span class="hljs-type">int</span> n, A, B, l = -INF, r = INF; <br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">while</span>(n--){<br>cin>>A>>B;<br>l = <span class="hljs-built_in">max</span>(l, A/(B + <span class="hljs-number">1</span>) + <span class="hljs-number">1</span>);<br>r = <span class="hljs-built_in">min</span>(r, A/B);<br>}<br>cout<<l<<<span class="hljs-string">" "</span><<r<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:并不难,主要是INF这里掌握不足,需要记住。</li></ul><h3 id="飞机降落:"><a href="#飞机降落:" class="headerlink" title="飞机降落:"></a>飞机降落:</h3><ul><li>描述:请你判断 <em>N</em> 架飞机是否可以全部安全降落。</li><li>思路:刚开始尝试贪心但是发现怎么都调不出来所有飞机的顺序,故而采取dfs遍历所有飞机的顺序,时间复杂度为O(N^2),主要注意book每次都要重置为0,不然会影响后面的使用。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">15</span>;<br><span class="hljs-type">int</span> T, n, book[<span class="hljs-number">15</span>]; <br><span class="hljs-keyword">struct</span> <span class="hljs-title class_">node</span>{<br><span class="hljs-type">int</span> t;<br><span class="hljs-type">int</span> d;<br><span class="hljs-type">int</span> l;<br>}p[N];<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> step, <span class="hljs-type">int</span> tim)</span></span>{<br><span class="hljs-keyword">if</span>(step > n) <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(book[i] == <span class="hljs-number">1</span> ) <span class="hljs-keyword">continue</span>;<br><span class="hljs-keyword">if</span>(p[i].t + p[i].d < tim) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>book[i] = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">dfs</span>(step + <span class="hljs-number">1</span>, <span class="hljs-built_in">max</span>(tim, p[i].t) + p[i].l)){<br><span class="hljs-keyword">return</span> <span class="hljs-number">1</span>;<br>}<br>book[i] = <span class="hljs-number">0</span>;<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>T;<br><span class="hljs-keyword">while</span>(T--){<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>p[i].t>>p[i].d>>p[i].l;<br>}<br><span class="hljs-built_in">memset</span>(book,<span class="hljs-number">0</span>,<span class="hljs-built_in">sizeof</span>(book));<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">dfs</span>(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>)) cout<<<span class="hljs-string">"YES"</span><<endl;<br><span class="hljs-keyword">else</span> cout<<<span class="hljs-string">"NO"</span><<endl; <br>}<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:for遍历dfs这种形式其实比较常见,注意要恢复现场,多多考虑清楚细节问题。</li></ul><h3 id="接龙数列:"><a href="#接龙数列:" class="headerlink" title="接龙数列:"></a>接龙数列:</h3><ul><li>描述:给定一个数组,判断最少去掉多少个元素可以使剩余数列为接龙数列</li><li>思路:最少不太好判断,可以转化一下思路,把解决的问题变为在原数组找最长的接龙子序列,那么就是一个线性dp问题了,把每个数字都当作字符串存储更容易使用。dp[c]表示以c为结尾的最长接龙子序列的长度,那么从头开始遍历序列,当前的字符串是s, dp[s[m-1] - 48] = max(dp[s[m-1] - 48], dp[s[0] - 48] + 1)。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br>string s;<br><span class="hljs-type">int</span> dp[<span class="hljs-number">15</span>], ans, n; <br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>s;<br><span class="hljs-type">int</span> m = s.<span class="hljs-built_in">length</span>();<br>dp[s[m<span class="hljs-number">-1</span>] - <span class="hljs-number">48</span>] = <span class="hljs-built_in">max</span>(dp[s[m<span class="hljs-number">-1</span>] - <span class="hljs-number">48</span>], dp[s[<span class="hljs-number">0</span>] - <span class="hljs-number">48</span>] + <span class="hljs-number">1</span>);<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i <= <span class="hljs-number">9</span>; i++){<br>ans = <span class="hljs-built_in">max</span>(ans, dp[i]);<br>}<br>cout<<n-ans<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:还是觉得很神奇的线性DP,从头开始遍历竟然就可以逐步解决子序列的求解,太简洁有力了~</li></ul><h3 id="抓娃娃:"><a href="#抓娃娃:" class="headerlink" title="抓娃娃:"></a>抓娃娃:</h3><ul><li>描述:套圈,给取多个区间,多条线段,线段覆盖区间一半以上算是套中,问每个线段可以套中几个</li><li>思路:套中其实相等于区间的中点在线段之内,那么求出所有的区间中点再前缀和一下,就可以O(1)求出套中的区间个数了。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1000050</span>;<br><span class="hljs-type">int</span> n, m, mp[N]; <br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>,l,r; i <= n; i++){<br>cin>>l>>r;<br>mp[l+r]++;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= N; i++){<br>mp[i] = mp[i<span class="hljs-number">-1</span>] + mp[i];<br>}<br><span class="hljs-type">int</span> l, r;<br><span class="hljs-keyword">while</span>(m--){<br>cin>>l>>r;<br>l *= <span class="hljs-number">2</span>;<br>r *= <span class="hljs-number">2</span>;<br>cout<<mp[r] - mp[l<span class="hljs-number">-1</span>]<<endl; <br>}<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:转化一下思路即可,注意求中点可能出现小数,最好都乘2来避免,这点已经不止一次遇到了。</li></ul><h3 id="子串简写:"><a href="#子串简写:" class="headerlink" title="子串简写:"></a>子串简写:</h3><ul><li>描述:子串Kubernetes可以简写成 K8s,我们规定长度大于等于 K 的字符串都可以采用这种简写方法。长度小于 K 的字符串不允许使用这种简写。给定一个字符串 S 和两个字符 c1 和 c2。请你计算 S 有多少个以 c1 开头 c2 结尾的子串可以采用这种简写?</li><li>思路:其实就是找对应的c1,c2组数,然后距离要大于等于k,为了降低时间复杂度,对c1的位置进行存储,然后找出最大的符合当前c2位置要求的位置。时间复杂度应当是NlogN。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-type">int</span> k, ans;<br>string s;<br><span class="hljs-type">char</span> c1,c2;<br>vector<<span class="hljs-type">int</span>> pc1;<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>k>>s>>c1>>c2;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < s.<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-keyword">if</span>(s[i] == c1){<br>pc1.<span class="hljs-built_in">push_back</span>(i);<br>}<br><span class="hljs-keyword">if</span>(s[i] == c2){<br><span class="hljs-keyword">if</span>(i - k + <span class="hljs-number">1</span> < <span class="hljs-number">0</span> || pc1.<span class="hljs-built_in">size</span>() == <span class="hljs-number">0</span>) <span class="hljs-keyword">continue</span>;<br><span class="hljs-type">int</span> l = <span class="hljs-number">0</span>, r = pc1.<span class="hljs-built_in">size</span>() - <span class="hljs-number">1</span>;<br><span class="hljs-keyword">while</span>(l < r){<br><span class="hljs-type">int</span> mid = (l + r + <span class="hljs-number">1</span>)>><span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(pc1[mid] <= i - k + <span class="hljs-number">1</span>) l = mid;<br><span class="hljs-keyword">else</span> r = mid - <span class="hljs-number">1</span>;<br>}<br><span class="hljs-keyword">if</span>(pc1[l] <= i - k + <span class="hljs-number">1</span>){<br>ans += l + <span class="hljs-number">1</span>;<br>}<br>}<br>}<br>cout<<ans<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:通过二分很有效地降低了时间复杂度,而且很简洁明了。关于二分的题目还是要重视,其要求就是存在一个临界点,找出这个临界点。另外,发现题目必须开long long才能过。所以比赛的时候不管三七二十一,最好都写上#define int long long,这样子会避免失去不必要失去的分数。</li></ul><h3 id="01串的熵"><a href="#01串的熵" class="headerlink" title="01串的熵"></a>01串的熵</h3><ul><li>描述:对于一个长度为23333333 的 01 串,如果其信息熵为 11625907.5798,且 0 出现次数比 1 少,那么这个01 串中 0 出现了多少次?</li><li>思路:模拟即可,0的个数0开始遍历,直到结果求出与所给的值一致</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-type">int</span> n = <span class="hljs-number">23333333</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i <= n/<span class="hljs-number">2</span>; i++){<br><span class="hljs-type">double</span> x = (<span class="hljs-number">-1.0</span>)*(<span class="hljs-number">1.0</span>*i/n)*<span class="hljs-built_in">log2</span>(<span class="hljs-number">1.0</span>*i/n)*i;<br><span class="hljs-type">double</span> y = (<span class="hljs-number">-1.0</span>)*(n-i)/n*<span class="hljs-built_in">log2</span>(<span class="hljs-number">1.0</span>*(n-i)/n)*(n-i);<br><span class="hljs-keyword">if</span>(x + y >= <span class="hljs-number">11625907.5798</span> && x + y <= <span class="hljs-number">11625907.5799</span>){<br>cout<<i<<endl;<br><span class="hljs-keyword">break</span>;<br>}<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:模拟并不困难,关键要注意整数型在进行<strong>除法运算时必须加入1.0这样的浮点数</strong>,否则会精度缺失;另外,最终的<strong>浮点数结果的判定</strong>也要选取x + y >= 11625907.5798 && x + y <= 11625907.5799这样的合理范围。</li></ul><h3 id="景区导游:"><a href="#景区导游:" class="headerlink" title="景区导游:"></a>景区导游:</h3><ul><li>描述:某景区一共有 N 个景点,编号 1 到 N。<br>景点之间共有 N − 1 条双向的摆渡车线路相连,形成一棵树状结构。<br>在景点之间往返只能通过这些摆渡车进行,需要花费一定的时间。<br>小明是这个景区的资深导游,他每天都要按固定顺序带客人游览其中 K 个景点:A1, A2, … , AK。 今天由于时间原因,小明决定跳过其中一个景点,只带游客按顺序游览其中 K − 1 个景点。<br>具体来说,如果小明选择跳过 Ai,那么他会按顺序带游客游览A1, A2, … , Ai−1, Ai+1, … , AK; (1 ≤ i ≤ K)。<br>请你对任意一个 Ai,计算如果跳过这个景点,小明需要花费多少时间在景点之间的摆渡车上?</li></ul><h4 id="解法一:暴力求树上两点距离"><a href="#解法一:暴力求树上两点距离" class="headerlink" title="解法一:暴力求树上两点距离"></a>解法一:暴力求树上两点距离</h4><ul><li>思路:通过dfs来求树上两点之间的距离,求出总的路线的sum,再遍历去掉每一个点,sum进行简单的加减。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">typedef</span> pair<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> PII;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">2e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, k, a[N], sum;<br>vector<PII> e[N];<br>map<PII, <span class="hljs-type">int</span>> st;<br><span class="hljs-function"><span class="hljs-type">bool</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> s, <span class="hljs-type">int</span> cur, <span class="hljs-type">int</span> last, <span class="hljs-type">int</span> v, <span class="hljs-type">int</span> sum)</span></span>{<br><span class="hljs-keyword">if</span>(cur == v){<br>st[{s, v}] = sum;<br>st[{v, s}] = sum;<br><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[cur].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> x = e[cur][i].first;<br><span class="hljs-keyword">if</span>(x == last) <span class="hljs-keyword">continue</span>;<br><span class="hljs-type">int</span> y = e[cur][i].second;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">dfs</span>(s, x, cur, v, sum + y)){<br><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>}<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>k;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>,u,v,t; i < n - <span class="hljs-number">1</span>;i++){<br>cin>>u>>v>>t;<br>e[u].<span class="hljs-built_in">push_back</span>({v, t});<br>e[v].<span class="hljs-built_in">push_back</span>({u, t});<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < k; i++) cin>>a[i];<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < k - <span class="hljs-number">1</span>; i++){<br><span class="hljs-built_in">dfs</span>(a[i], a[i], <span class="hljs-number">-1</span>, a[i + <span class="hljs-number">1</span>], <span class="hljs-number">0</span>);<br>sum += st[{a[i], a[i + <span class="hljs-number">1</span>]}];<br>}<br><span class="hljs-type">int</span> res;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < k; i++){<br><span class="hljs-keyword">if</span>(i == <span class="hljs-number">0</span>){<br><span class="hljs-comment">//dfs(a[i], a[i], -1, a[i + 1], 0);</span><br>res = sum - st[{a[i], a[i + <span class="hljs-number">1</span>]}];<br>}<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(i == k - <span class="hljs-number">1</span>){<br><span class="hljs-comment">//dfs(a[i-1], a[i-1], -1, a[i], 0);</span><br>res = sum - st[{a[i<span class="hljs-number">-1</span>], a[i]}];<br>}<span class="hljs-keyword">else</span>{<br><span class="hljs-built_in">dfs</span>(a[i<span class="hljs-number">-1</span>], a[i<span class="hljs-number">-1</span>], <span class="hljs-number">-1</span>, a[i+<span class="hljs-number">1</span>], <span class="hljs-number">0</span>);<br>res = sum - st[{a[i<span class="hljs-number">-1</span>],a[i]}] - st[{a[i], a[i+<span class="hljs-number">1</span>]}] + st[{a[i<span class="hljs-number">-1</span>], a[i+<span class="hljs-number">1</span>]}];<br>}<br>cout<<res<<endl;<br>}<br><br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:是一种暴力解法,关键在于树上两点距离的dfs求解,其实这类题目的套路基本已经很熟悉了,还是要勇敢去做,去尝试。这是一道很棒的练手题~</li></ul><h4 id="解法二:树上前缀和-LCA"><a href="#解法二:树上前缀和-LCA" class="headerlink" title="解法二:树上前缀和+LCA"></a>解法二:树上前缀和+LCA</h4><ul><li>思路:暴力的时间复杂度只要体现在每次都要dfs来求两点之间距离,可以利用树上前缀和,先预处理每个点到根节点的距离,那么两点间距离=sum[u]+sum[v]- 2*sum[lca(u,v)]。时间复杂度变为O(N)+O(logN)</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-keyword">typedef</span> pair<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> PII;<br><span class="hljs-type">int</span> n, k, a[N], sum[N];<br>vector<PII> e[N];<br><span class="hljs-type">int</span> siz[N], dep[N], top[N], fa[N], son[N];<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs1</span><span class="hljs-params">(<span class="hljs-type">int</span> u ,<span class="hljs-type">int</span> father)</span></span>{<span class="hljs-comment">//(1,0)</span><br>siz[u] = <span class="hljs-number">1</span>;<br>dep[u] = dep[father] + <span class="hljs-number">1</span>;<br>fa[u] = father;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> s = e[u][i].first;<br><span class="hljs-keyword">if</span>(s == fa[u]) <span class="hljs-keyword">continue</span>;<br><span class="hljs-built_in">dfs1</span>(s, u);<br>siz[u] += siz[s];<br><span class="hljs-keyword">if</span>(siz[son[u]] < siz[s]){<br>son[u] = s;<br>}<br>}<br>}<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs2</span><span class="hljs-params">(<span class="hljs-type">int</span> u ,<span class="hljs-type">int</span> t)</span></span>{<span class="hljs-comment">//(1,1)</span><br>top[u] = t;<br><span class="hljs-keyword">if</span>(son[u] == <span class="hljs-number">0</span>) <span class="hljs-keyword">return</span>;<br><span class="hljs-built_in">dfs2</span>(son[u], t);<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> s = e[u][i].first;<br><span class="hljs-keyword">if</span>(s == fa[u] || s == son[u]) <span class="hljs-keyword">continue</span>;<br><span class="hljs-built_in">dfs2</span>(s, s);<br>}<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">lca</span><span class="hljs-params">(<span class="hljs-type">int</span> x, <span class="hljs-type">int</span> y)</span></span>{<br><span class="hljs-keyword">while</span>(top[x] != top[y]){<br><span class="hljs-keyword">if</span>(dep[top[x]] < dep[top[y]]){<br><span class="hljs-built_in">swap</span>(x, y);<br>}<br>x = fa[top[x]];<br>}<br><span class="hljs-keyword">return</span> dep[x] < dep[y]? x : y;<br>}<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">cal_sum</span><span class="hljs-params">(<span class="hljs-type">int</span> u)</span></span>{<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> x = e[u][i].first;<br><span class="hljs-keyword">if</span>(x == fa[u]) <span class="hljs-keyword">continue</span>;<br><span class="hljs-type">int</span> y = e[u][i].second;<br>sum[x] = sum[u] + y;<br><span class="hljs-built_in">cal_sum</span>(x);<br>}<br>}<br><br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>k;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>, u, v, t; i < n - <span class="hljs-number">1</span>; i++){<br>cin>>u>>v>>t;<br>e[u].<span class="hljs-built_in">push_back</span>({v, t});<br>e[v].<span class="hljs-built_in">push_back</span>({u, t});<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= k; i++){<br>cin>>a[i];<br>}<br><span class="hljs-built_in">dfs1</span>(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>);<br><span class="hljs-built_in">dfs2</span>(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>);<br><br><span class="hljs-built_in">cal_sum</span>(<span class="hljs-number">1</span>);<br><br><span class="hljs-type">int</span> ans = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= k - <span class="hljs-number">1</span>; i++){<br><span class="hljs-type">int</span> u = a[i], v = a[i + <span class="hljs-number">1</span>];<br><span class="hljs-type">int</span> cost = sum[u] + sum[v] - <span class="hljs-number">2</span>*sum[<span class="hljs-built_in">lca</span>(u,v)];<br>ans += cost;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= k; i++){<br><span class="hljs-type">int</span> tmp = ans, w = a[i - <span class="hljs-number">1</span>], u = a[i], v = a[i + <span class="hljs-number">1</span>];<br><span class="hljs-keyword">if</span>(i == <span class="hljs-number">1</span>){<br>tmp -= sum[u] + sum[v] - <span class="hljs-number">2</span>*sum[<span class="hljs-built_in">lca</span>(u,v)]; <br>}<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(i == k){<br>tmp -= sum[w] + sum[u] - <span class="hljs-number">2</span>*sum[<span class="hljs-built_in">lca</span>(u,w)];<br>}<span class="hljs-keyword">else</span>{<br>tmp = tmp - (sum[u] + sum[v] - <span class="hljs-number">2</span>*sum[<span class="hljs-built_in">lca</span>(u,v)])-(sum[w] + sum[u] - <span class="hljs-number">2</span>*sum[<span class="hljs-built_in">lca</span>(u,w)])<br>+(sum[v] + sum[w] - <span class="hljs-number">2</span>*sum[<span class="hljs-built_in">lca</span>(w,v)]);<br>}<br>cout<<tmp<<<span class="hljs-string">" "</span>;<br>}<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:看来lca的用途还是很广的,可以再多多联系以达到熟练的程度。可以和砍树这道题联合起来看。关键在于lca的板子熟练,目前基本可以敲下来了,还需要不时的练习。</li></ul><h3 id="整数删除:"><a href="#整数删除:" class="headerlink" title="整数删除:"></a>整数删除:</h3><ul><li>描述:给定一个长度为 N 的整数数列:A1, A2, … , AN。你要重复以下操作 K 次:<br>每次选择数列中最小的整数(如果最小值不止一个,选择最靠前的),将其删除。<br>并把与它相邻的整数加上被删除的数值。<br>输出 K 次操作后的序列</li></ul><h4 id="解法一:暴力模拟"><a href="#解法一:暴力模拟" class="headerlink" title="解法一:暴力模拟"></a>解法一:暴力模拟</h4><ul><li>思路:直接对过程进行模拟,能拿到20%的分数,主要是相邻的数相加这里要考虑存在删除了的数,再加两个循环遍历。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> INF 0x3f3f3f3f3f3f3f</span><br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">5e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, k, a[N], vis[N];<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>k;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>a[i];<br>}<br><span class="hljs-keyword">while</span>(k--){<br><span class="hljs-type">int</span> minn = INF, pos = <span class="hljs-number">-1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(vis[i]==<span class="hljs-number">0</span> && a[i] < minn){<br>minn = a[i];<br>pos = i;<br>}<br>}<br>vis[pos] = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = pos - <span class="hljs-number">1</span>; j >= <span class="hljs-number">0</span>; j --)<br>{<br><span class="hljs-keyword">if</span>(!vis[j])<br>{<br>a[j] += minn;<br><span class="hljs-keyword">break</span>;<br>}<br>}<br><br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = pos + <span class="hljs-number">1</span>; j < n; j ++)<br>{<br><span class="hljs-keyword">if</span>(!vis[j])<br>{<br>a[j] += minn;<br><span class="hljs-keyword">break</span>;<br>}<br>}<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(vis[i] == <span class="hljs-number">0</span>){<br>cout<<a[i]<<<span class="hljs-string">" "</span>;<br>}<br>} <br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:能直接模拟出来快速拿到部分分也是个不错的选择,至少是个保底,当然能正确模拟也是很重要的。</li></ul><h4 id="解法二:链表-优先队列"><a href="#解法二:链表-优先队列" class="headerlink" title="解法二:链表+优先队列"></a>解法二:链表+优先队列</h4><ul><li><p>思路:暴力解法的时间复杂度主要体现在寻找最小值以及找未被删除的相邻节点,可以使用小根堆(优先队列)降低寻找最小值的时间复杂度为O(logN),再用双向队列(两个数组)维护相邻节点。</p></li><li><p>代码:</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">typedef</span> pair<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> pii;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">5e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, k, a[N], st[N], l[N], r[N]; <br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>k;<br>priority_queue<pii, vector<pii>, greater<pii>> q;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br>cin>>a[i];<br>q.<span class="hljs-built_in">push</span>({a[i], i});<br>st[i] = a[i];<br>l[i] = i - <span class="hljs-number">1</span>;<br>r[i] = i + <span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(i == n - <span class="hljs-number">1</span>) r[i] = <span class="hljs-number">-1</span>;<br>}<br><br><span class="hljs-keyword">while</span>(k){<br>pii t = q.<span class="hljs-built_in">top</span>();<br>q.<span class="hljs-built_in">pop</span>();<br><span class="hljs-keyword">if</span>(t.first != st[t.second]){<br>q.<span class="hljs-built_in">push</span>({st[t.second], t.second});<br><span class="hljs-keyword">continue</span>;<br>}<br>k--;<br><span class="hljs-type">int</span> pos = t.second;<br><span class="hljs-keyword">if</span>(l[pos] >= <span class="hljs-number">0</span>) st[l[pos]] += t.first;<br><span class="hljs-keyword">if</span>(r[pos] >= <span class="hljs-number">0</span>) st[r[pos]] += t.first;<br><br><span class="hljs-keyword">if</span>(l[pos] >= <span class="hljs-number">0</span>) r[l[pos]] = r[pos];<br><span class="hljs-keyword">if</span>(r[pos] >= <span class="hljs-number">0</span>) l[r[pos]] = l[pos];<br>st[pos] = <span class="hljs-number">-1</span>;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br><span class="hljs-keyword">if</span>(st[i] != <span class="hljs-number">-1</span>){<br>cout<<st[i]<<<span class="hljs-string">" "</span>;<br>}<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:一些细节问题可以学习,比如<strong>修改值,就是先取,发现值有了更新就加上放回去再重新取</strong>,直到没有改变多了,再k–,这点很巧妙。这是由于小根堆的特点,取最小值比较快。不能直接找出那个要加的值,取出再放回,那么小根堆就失去优势了。</li></ul><h3 id="砍树:"><a href="#砍树:" class="headerlink" title="砍树:"></a>砍树:</h3><h4 id="解法一:暴力53"><a href="#解法一:暴力53" class="headerlink" title="解法一:暴力53%"></a>解法一:暴力53%</h4><ul><li>描述:给定一棵由 n 个结点组成的树以及 m 个不重复的无序数对(a1, b1), (a2, b2), … , (am, bm),其中 ai 互不相同,bi 互不相同,ai ≠ bj(1 ≤ i, j ≤ m)。<br>小明想知道是否能够选择一条树上的边砍断,使得对于每个 (ai, bi) 满足 ai 和bi 不连通。<br>如果可以则输出应该断掉的边的编号(编号按输入顺序从 1 开始),否则输出-1。</li><li>思路:根据描述,对于每一对序号,找到它们的公共边即可实现,那怎么找呢?可以dfs每对序号,从一端找到另一端,在dfs的过程中标记走过的边,最终边的权重为m的就是在删除范围内的边了,再找到编号最大的即可。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-keyword">typedef</span> pair<<span class="hljs-type">int</span> ,<span class="hljs-type">int</span>> PII;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>; <br><span class="hljs-type">int</span> n, m, w[N];<br>vector<<span class="hljs-type">int</span>> e[N];<br>map<PII, <span class="hljs-type">int</span>> id;<br><span class="hljs-function"><span class="hljs-type">bool</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> s, <span class="hljs-type">int</span> u, <span class="hljs-type">int</span> father, <span class="hljs-type">int</span> v)</span></span>{<br><span class="hljs-keyword">if</span>(u == v) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i++){<br><span class="hljs-type">int</span> cur = e[u][i];<br><span class="hljs-keyword">if</span>(cur == father) <span class="hljs-keyword">continue</span>;<br><span class="hljs-keyword">if</span>(<span class="hljs-built_in">dfs</span>(s, cur, u, v)){<br><span class="hljs-type">int</span> ID = id[{cur, u}];<br>w[ID]++;<br><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br>}<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>, u, v; i < n<span class="hljs-number">-1</span>; i++){<br>cin>>u>>v;<br>e[u].<span class="hljs-built_in">push_back</span>(v);<br>e[v].<span class="hljs-built_in">push_back</span>(u);<br>id[{u,v}] = i;<br>id[{v,u}] = i;<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>, u, v; i < m; i++){<br>cin>>u>>v;<br><span class="hljs-built_in">dfs</span>(u,u,<span class="hljs-number">-1</span>,v); <br>}<br><span class="hljs-type">int</span> ans = <span class="hljs-number">-1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = n<span class="hljs-number">-1</span>; i>=<span class="hljs-number">0</span>; i--){<br><span class="hljs-keyword">if</span>(w[i] == m){<br>ans = i + <span class="hljs-number">1</span>;<br><span class="hljs-keyword">break</span>;<br>}<br>}<br>cout<<ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:思路并不难,但是一遇到树就容易犯怵,一点想法也没有,其实刚开始不要给自己太大压力,就慢慢一步一步地想,去模拟样例是怎么实现的,再去和dfs联系起来,熟能生巧叭~</li></ul><h4 id="解法二:lca-树上差分"><a href="#解法二:lca-树上差分" class="headerlink" title="解法二:lca+树上差分"></a>解法二:lca+树上差分</h4><ul><li>思路:优化给边打标记的过程,先边权转化为点权,对于一对序号,对它的两个端点序号++,它们的公共祖先序号-2,最后对每个点点权进行累计为它为根的所在子树的权重即可,边就是这个点上面的一条边。使用树链剖分来实现lca。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-keyword">typedef</span> pair<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> pii;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">1e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, m, w[N];<br>vector<<span class="hljs-type">int</span>> e[N];<br>map<pii, <span class="hljs-type">int</span>> id;<br><br><span class="hljs-type">int</span> siz[N], top[N], dep[N], fa[N], son[N];<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs1</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> father)</span></span><br><span class="hljs-function"></span>{<br>siz[u] = <span class="hljs-number">1</span>, dep[u] = dep[father] + <span class="hljs-number">1</span>;<br>fa[u] = father;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i ++)<br>{<br><span class="hljs-type">int</span> s = e[u][i];<br><span class="hljs-keyword">if</span>(s == fa[u])<br><span class="hljs-keyword">continue</span>;<br><span class="hljs-built_in">dfs1</span>(s, u);<br>siz[u] += siz[s];<br><span class="hljs-keyword">if</span>(siz[son[u]] < siz[s])<br>son[u] = s;<br>}<br>}<br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs2</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> t)</span></span><br><span class="hljs-function"></span>{<br>top[u] = t;<br><span class="hljs-keyword">if</span>(son[u] == <span class="hljs-number">0</span>)<br><span class="hljs-keyword">return</span>;<br><span class="hljs-built_in">dfs2</span>(son[u], t);<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i ++)<br>{<br><span class="hljs-type">int</span> s = e[u][i];<br><span class="hljs-keyword">if</span>(s == fa[u] || s == son[u])<br><span class="hljs-keyword">continue</span>;<br><span class="hljs-built_in">dfs2</span>(s, s);<br>}<br>}<br><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">lca</span><span class="hljs-params">(<span class="hljs-type">int</span> x, <span class="hljs-type">int</span> y)</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-keyword">while</span>(top[x] != top[y])<br>{<br><span class="hljs-keyword">if</span>(dep[top[x]] < dep[top[y]])<br><span class="hljs-built_in">swap</span>(x, y);<br><br>x = fa[top[x]];<br>}<br><span class="hljs-keyword">return</span> dep[x] < dep[y] ? x : y;<br>}<br><br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">cal_sum</span><span class="hljs-params">(<span class="hljs-type">int</span> u, <span class="hljs-type">int</span> father)</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < e[u].<span class="hljs-built_in">size</span>(); i ++)<br>{<br><span class="hljs-type">int</span> son = e[u][i];<br><span class="hljs-keyword">if</span>(son == father)<br><span class="hljs-keyword">continue</span>;<br><span class="hljs-built_in">cal_sum</span>(son, u);<br>w[u] += w[son];<br>}<br>}<br><br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n - <span class="hljs-number">1</span>; i++){<br><span class="hljs-type">int</span> x,y;<br>cin>>x>>y;<br>e[x].<span class="hljs-built_in">push_back</span>(y);<br>e[y].<span class="hljs-built_in">push_back</span>(x);<br>id[{x,y}] = id[{y,x}] = i;<br>}<br><span class="hljs-built_in">dfs1</span>(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>);<br><span class="hljs-built_in">dfs2</span>(<span class="hljs-number">1</span>, <span class="hljs-number">1</span>);<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < m; i++){<br><span class="hljs-type">int</span> a,b;<br>cin>>a>>b;<br>w[a]++;<br>w[b]++;<br>w[<span class="hljs-built_in">lca</span>(a,b)] -= <span class="hljs-number">2</span>;<br>}<br><span class="hljs-built_in">cal_sum</span>(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>);<br><span class="hljs-type">int</span> ans = <span class="hljs-number">-1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br><span class="hljs-keyword">if</span>(w[i] == m){<br><span class="hljs-type">int</span> ID = id[{i, fa[i]}];<br>ans = <span class="hljs-built_in">max</span>(ID, ans);<br>}<br>}<br>cout<<ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:一个是lca,一个是树上差分,树上差分主要用于树上一段路径的+1,需要熟悉模板以及解决问题的思路是怎么推出来的,很有挑战的一道题目,但是可以理解的。模板要尽可能地熟练。</li></ul>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>蓝桥杯</tag>
</tags>
</entry>
<entry>
<title>蓝桥杯真题训练-2023年省赛A组</title>
<link href="/2024/03/02/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%9F%E9%A2%98%E8%AE%AD%E7%BB%83/"/>
<url>/2024/03/02/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%81%E8%B5%9B%E5%A4%87%E8%B5%9B/%E8%93%9D%E6%A1%A5%E6%9D%AF%E7%9C%9F%E9%A2%98%E8%AE%AD%E7%BB%83/</url>
<content type="html"><![CDATA[<h2 id="2023年省赛题目A组"><a href="#2023年省赛题目A组" class="headerlink" title="2023年省赛题目A组"></a>2023年省赛题目A组</h2><h3 id="A幸运数:"><a href="#A幸运数:" class="headerlink" title="A幸运数:"></a>A幸运数:</h3><ul><li><p>描述:小蓝认为如果一个数含有偶数个数位,并且前面一半的数位之和等于后面一半的数位之和,则这个数是他的幸运数字。例如 2314 是一个幸运数字,因为它有 44 个数位,并且 2+3=1+4。现在请你帮他计算从 1 至 100000000 之间共有多少个不同的幸运数字。</p></li><li><p>思路:10^8刚好是上界,可以直接进行模拟运算,首先计算数的位数,如果是奇数直接跳过,是偶数的话,再计算平分两部分的数值累积,如果相等计入答案。</p></li><li><p>代码:</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span>{<br><span class="hljs-comment">//int ans = 0;</span><br><span class="hljs-comment">//for(int i = 1; i <= 100000000; i++){</span><br><span class="hljs-comment">//int cnt = 0;</span><br><span class="hljs-comment">//for(int j = i; j != 0; j/=10){</span><br><span class="hljs-comment">//cnt++;</span><br><span class="hljs-comment">//}</span><br><span class="hljs-comment">//if(cnt % 2 == 1) continue;</span><br><span class="hljs-comment">//int now = 0, sum = 0;</span><br><span class="hljs-comment">//for(int j = i;j != 0; j/=10){</span><br><span class="hljs-comment">//now++;</span><br><span class="hljs-comment">//if(now <= cnt/2) sum += j % 10;</span><br><span class="hljs-comment">//else sum -= j % 10; </span><br><span class="hljs-comment">//}</span><br><span class="hljs-comment">//if(sum == 0) ans++;</span><br><span class="hljs-comment">//}</span><br><span class="hljs-comment">//cout<<ans<<endl;</span><br><span class="hljs-built_in">puts</span>(<span class="hljs-string">"4430091"</span>);<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>} <br></code></pre></td></tr></table></figure><ul><li>总结:第一道题一般都是直接模拟的题目,不用考虑太多时间复杂度,关键在于老老实实清晰模拟过程即可</li></ul><h3 id="B有奖问答"><a href="#B有奖问答" class="headerlink" title="B有奖问答"></a>B有奖问答</h3><ul><li>描述:<ul><li>小蓝正在参与一个现场问答的节目。活动中一共有 30 道题目,每题只有答对和答错两种情况,每答对一题得 10 分,答错一题分数归零。小蓝可以在任意时刻结束答题并获得目前分数对应的奖项,之后不能再答任何题目。最高奖项需要 100 分,所以到达 100 分时小蓝会直接停止答题。已知小蓝最终实际获得了 70 分对应的奖项,请问小蓝所有可能的答题情况有多少种?</li></ul></li></ul><h4 id="解法一:dfs"><a href="#解法一:dfs" class="headerlink" title="解法一:dfs"></a>解法一:dfs</h4><ul><li>思路:采用dfs,不断向下深搜,返回结果条件为到达30题或100分,分支为当前题目做对或做错</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> ans;<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> step, <span class="hljs-type">int</span> score)</span></span>{<br><span class="hljs-keyword">if</span>(score == <span class="hljs-number">70</span>) ans++;<br><span class="hljs-keyword">if</span>(step == <span class="hljs-number">31</span> || score == <span class="hljs-number">100</span>) <span class="hljs-keyword">return</span>;<br><span class="hljs-built_in">dfs</span>(step + <span class="hljs-number">1</span>, score + <span class="hljs-number">10</span>);<br><span class="hljs-built_in">dfs</span>(step + <span class="hljs-number">1</span>, <span class="hljs-number">0</span>); <br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-built_in">dfs</span>(<span class="hljs-number">1</span>, <span class="hljs-number">0</span>);<br>cout<<ans<<endl;<br><span class="hljs-built_in">puts</span>(<span class="hljs-string">"8335366"</span>);<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:其实是很明显的dfs,还是不够熟悉,熟能生巧,很棒的一道基础题。</li></ul><h4 id="解法二:dp"><a href="#解法二:dp" class="headerlink" title="解法二:dp"></a>解法二:dp</h4><ul><li>思路:发现相关的前后状态是有联系的,可以采取dp解决。dp(i)(j)表示做了i道题得分为j的方案数,分数先统一/10。<ul><li>那么当j!=10时,dp(i)(0) += dp(i-1)(j),相当于此时最终得分为0,那么这i道题最后一道肯定是答错的,前i-1道题任意组合,那么就是dp(i-1)(j)的累加,但是j不能等于10,因为这表示已经满分了,不会再进行答题。</li><li>那么当j!=0时,dp(i)(j) = dp(i-1)(j-1),表示当前第i道题肯定是答对的,那么前i-1道题得分为j-1的方案数就是之前算出来的dp(i-1)(j-1)</li><li>总的来说,还是当前这第i道题是答对还是答错,答错就是之前的累加,答对就是左上角的方案数。列出对应的二维表会非常清晰</li></ul></li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> dp[<span class="hljs-number">35</span>][<span class="hljs-number">15</span>], ans; <br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>dp[<span class="hljs-number">0</span>][<span class="hljs-number">0</span>] = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= <span class="hljs-number">30</span>; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">0</span>; j <= <span class="hljs-number">10</span>; j++){<br><span class="hljs-keyword">if</span>(j != <span class="hljs-number">10</span>){<br>dp[i][<span class="hljs-number">0</span>] += dp[i<span class="hljs-number">-1</span>][j];<br>}<br><span class="hljs-keyword">if</span>(j != <span class="hljs-number">0</span>){<br>dp[i][j] = dp[i<span class="hljs-number">-1</span>][j<span class="hljs-number">-1</span>];<br>}<br>}<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i<= <span class="hljs-number">30</span>; i++){<br>ans+=dp[i][<span class="hljs-number">7</span>];<br>}<br>cout<<ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:其实可以算是一道背包问题,只有一个特殊点就是分数到100就停止答题了。对于这类较为基础的dp还是有多多联系,是可以拿下的。</li></ul><h3 id="C平方差"><a href="#C平方差" class="headerlink" title="C平方差"></a>C平方差</h3><ul><li>描述:给定 L,R,问 L≤x≤R 中有多少个 x 满足存在整数 y,z,使得 x = y2 - z2。</li><li>思路:通过展开平方差即x = (y + z)*(y - z),可知x是奇数或是4的倍数,那么直接计算这两个的个数即可</li><li>代码1:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> odd, four,l,r; <br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>l>>r;<br><span class="hljs-type">int</span> cnt = r - l + <span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(cnt % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>) odd = cnt / <span class="hljs-number">2</span>;<br><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(l % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>) odd = cnt /<span class="hljs-number">2</span>;<br><span class="hljs-keyword">else</span> odd = cnt / <span class="hljs-number">2</span> + <span class="hljs-number">1</span>;<br><br><span class="hljs-keyword">if</span>(cnt % <span class="hljs-number">4</span> == <span class="hljs-number">0</span>) four = cnt / <span class="hljs-number">4</span>;<br><span class="hljs-keyword">else</span>{<br><span class="hljs-type">int</span> yu = cnt % <span class="hljs-number">4</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= yu; i++){<br><span class="hljs-keyword">if</span>((l + i - <span class="hljs-number">1</span>) % <span class="hljs-number">4</span> == <span class="hljs-number">0</span>){<br>four = <span class="hljs-number">1</span>;<br>}<br>}<br>four += cnt / <span class="hljs-number">4</span>;<br>}<br>cout<< odd + four<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>代码2:当计算分支比较多时,可以考虑反方向计算,可能会更加简单</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><iostream></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br> <span class="hljs-type">int</span> l, r, ans = <span class="hljs-number">0</span>; <span class="hljs-comment">//ans为不满足的条件</span><br> cin>>l>>r; <br> <span class="hljs-type">int</span> x = r / <span class="hljs-number">2</span> - (l<span class="hljs-number">-1</span>) / <span class="hljs-number">2</span>; <span class="hljs-comment">//2的倍数</span><br> <span class="hljs-type">int</span> y = r / <span class="hljs-number">4</span> - (l<span class="hljs-number">-1</span>) / <span class="hljs-number">4</span>; <span class="hljs-comment">//4的倍数</span><br> ans = x - y; <span class="hljs-comment">//不满足条件</span><br> <span class="hljs-comment">//cout<<x<<" "<<y<<endl;</span><br> cout<<(r - l + <span class="hljs-number">1</span>) - ans; <span class="hljs-comment">//总数 - 不满足条件</span><br> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:当时这道题目应该是做出来了的,只要认真分析题目所给条件并不难,或者通过找规律也可以找到解题线索。</li></ul><h3 id="D更小的数"><a href="#D更小的数" class="headerlink" title="D更小的数"></a>D更小的数</h3><ul><li>描述:小蓝有一个长度均为 n 且仅由数字字符 0 ~ 9 组成的字符串,下标从 0 到 n - 1。<br>你可以将其视作是一个具有 n 位的十进制数字 num。<br>小蓝可以从 num 中选出一段连续的子串并将子串进行反转,最多反转一次。<br>小蓝想要将选出的子串进行反转后再放入原位置处得到的新的数字 numnew 满足条件numnew < num。<br>请你帮他计算下一共有多少种不同的子串选择方案。<br>只要两个子串在 num 中的位置不完全相同我们就视作是不同的方案。<br>注意,我们允许前导零的存在,即数字的最高位可以是 0 ,这是合法的</li></ul><h4 id="解法一:dp"><a href="#解法一:dp" class="headerlink" title="解法一:dp"></a>解法一:dp</h4><ul><li><p>思路:采取区间dp,发现若对任意的l,r,先比较的是s[l]和s[r],如果s[l]>s[r]则方案数加1,等于则看是s[l + 1]和s[r - 1],小于就是0。可以看到是存在<strong>子问题重叠</strong>的,子问题的最优解能代表整个问题的最优解。另外,这种二维dp的遍历方式一般都是先遍历长度再遍历左节点。</p></li><li><p>代码:</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> dp[<span class="hljs-number">5050</span>][<span class="hljs-number">5050</span>],ans; <br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>string s;<br>cin>>s;<br><span class="hljs-type">int</span> n = s.<span class="hljs-built_in">size</span>();<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> len = <span class="hljs-number">2</span>; len <= n; len ++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> l = <span class="hljs-number">0</span>; l + len - <span class="hljs-number">1</span> < n; l++){<br><span class="hljs-type">int</span> r = l + len - <span class="hljs-number">1</span>;<br><span class="hljs-keyword">if</span>(s[l] > s[r]) dp[l][r] = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(s[l] == s[r]) dp[l][r] = dp[l + <span class="hljs-number">1</span>][r<span class="hljs-number">-1</span>];<br>ans += dp[l][r];<br>}<br>}<br>cout<<ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:并不是很负责的区间dp,需要仔细分析通用情况,要多多熟练这种题型呀~</li></ul><h4 id="解法二:常规"><a href="#解法二:常规" class="headerlink" title="解法二:常规"></a>解法二:常规</h4><ul><li>思路:双重循环遍历,相等的情况直接算不行,但是当产生一个可行时,由里向外检查相同的情况,也算是可行方案,时间复杂也是O(N^2)。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br>string s;<br><span class="hljs-type">int</span> ans;<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>s;<br><span class="hljs-type">int</span> n = s.<span class="hljs-built_in">size</span>();<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < n; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = i + <span class="hljs-number">1</span>; j < n;j++){<br><span class="hljs-keyword">if</span>(s[i] <= s[j]) <span class="hljs-keyword">continue</span>;<br>ans++;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> k = <span class="hljs-number">1</span>; i - k >=<span class="hljs-number">0</span> && j + k <=n; k++){<br><span class="hljs-keyword">if</span>(s[i - k] == s[j + k]) ans++;<br><span class="hljs-keyword">else</span> <span class="hljs-keyword">break</span>; <span class="hljs-comment">//剪枝</span><br>}<br>}<br>}<br>cout<<ans<<endl;<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:也是很巧妙的做法,尤其是由里向外扩展检查这一步,时间复杂度应该也是O(N^2),空间复杂度相对较低,为O(1)。</li></ul><h3 id="H异或和之和"><a href="#H异或和之和" class="headerlink" title="H异或和之和"></a>H异或和之和</h3><ul><li>描述:给定一个数组 A[i],分别求其每个子段的异或和,并求出它们的和。或者说,对于每组满足 1≤<em>L</em>≤<em>R</em>≤<em>n</em> 的 L*,<em>R,求出数组中第 L 至第 R 个元素的异或和。然后输出每组L</em>,*R得到的结果加起来的值。</li><li>思路:连续异或具有<strong>前缀和</strong>的性质,即S[l,r]表示l到r的异或和等于S[r]^S[l-1],另外异或是针对位来说的,可以把每个数字都<strong>按位拆解</strong>。按照类似前缀和的方式求出每个S[i],那么它们要么是0,要么是1,进行任意组合的方案数就是<strong>0的个数乘以1的个数,再乘回当前位的权重</strong>累加就是最终结果了。注意计算0,1个数要从0开始。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long </span><br><span class="hljs-type">int</span> n, a[<span class="hljs-number">100050</span>], cnt[<span class="hljs-number">2</span>], sum, s[<span class="hljs-number">100050</span>];<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++) cin>>a[i];<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i <= <span class="hljs-number">20</span>; i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br><span class="hljs-keyword">if</span>((a[j]>>i) & <span class="hljs-number">1</span>) s[j] = s[j - <span class="hljs-number">1</span>] ^ <span class="hljs-number">1</span>;<br><span class="hljs-keyword">else</span> s[j] = s[j - <span class="hljs-number">1</span>];<br>}<br>cnt[<span class="hljs-number">0</span>] = cnt[<span class="hljs-number">1</span>] = <span class="hljs-number">0</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> k = <span class="hljs-number">0</span>; k <= n; k++){ <span class="hljs-comment">//参考前缀和,s[0]也要包括进来,因为s[i]和s[j]的异或实际表示的是a[i+1]到a[j]的异或和</span><br>cnt[s[k]]++; <br>}<br>sum += (<span class="hljs-number">1ll</span> << i) * cnt[<span class="hljs-number">0</span>] * cnt[<span class="hljs-number">1</span>];<br>}<br>cout<<sum<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:针对位运算的一道题,异或性质和前缀和的性质竟然是类似的,很有意思,一个全新的视角解决了这道题。</li></ul><h3 id="F买瓜"><a href="#F买瓜" class="headerlink" title="F买瓜"></a>F买瓜</h3><ul><li><p>描述:小蓝正在一个瓜摊上买瓜。瓜摊上共有 n 个瓜,每个瓜的重量为Ai。小蓝刀功了得,他可以把任何瓜劈成完全等重的两份,不过每个瓜只能劈一刀。小蓝希望买到的瓜的重量的和恰好为 m。</p><p>请问小蓝至少要劈多少个瓜才能买到重量恰好为 m 的瓜。如果无论怎样小蓝都无法得到总重恰好为 m 的瓜,请输出 −1。</p></li></ul><h4 id="解法一:暴力dfs-剪枝"><a href="#解法一:暴力dfs-剪枝" class="headerlink" title="解法一:暴力dfs+剪枝"></a>解法一:暴力dfs+剪枝</h4><ul><li>思路:每种瓜都有三种可能,不买,劈了买,不劈买,遍历三种可能然后不断往下递归,直到越界或者找到正确答案。由于0.5不好计算,可以把所有重量均乘以2。</li><li>代码:</li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">int</span> n, a[<span class="hljs-number">35</span>], ans = <span class="hljs-number">35</span>;<br><span class="hljs-type">long</span> <span class="hljs-type">long</span> m; <br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> step, <span class="hljs-type">int</span> status, <span class="hljs-type">int</span> cnt, <span class="hljs-type">long</span> <span class="hljs-type">long</span> sum)</span></span>{<br><span class="hljs-keyword">if</span>(sum > m) <span class="hljs-keyword">return</span>;<br><span class="hljs-keyword">if</span>(step > n){<br><span class="hljs-keyword">if</span>(sum == m) ans = <span class="hljs-built_in">min</span>(ans, cnt);<br><span class="hljs-keyword">return</span>;<br>} <br><span class="hljs-keyword">if</span>(status == <span class="hljs-number">0</span>) sum += <span class="hljs-number">2</span> * a[step];<br><span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(status == <span class="hljs-number">1</span>) sum += a[step], cnt++;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-number">3</span>; i++) <span class="hljs-built_in">dfs</span>(step + <span class="hljs-number">1</span>, i, cnt, sum);<br><span class="hljs-keyword">return</span>;<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n>>m;<br>m = m * <span class="hljs-number">2</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n; i++){<br>cin>>a[i];<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">0</span>; i < <span class="hljs-number">3</span>; i++){<br><span class="hljs-built_in">dfs</span>(<span class="hljs-number">1</span>, i, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>);<br>}<br>cout<<ans<<endl;<br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:暴力的本质就是递归,其实就是先遍历当前瓜的所有可能,然后再往下递归下一个瓜的所有可能,对于这种暴力模拟做法还是要掌握的。</li></ul><h3 id="E颜色平衡树"><a href="#E颜色平衡树" class="headerlink" title="E颜色平衡树"></a>E颜色平衡树</h3><ul><li><p>描述:给定一棵树,结点由 1至 n 编号,其中结点 1 是树根。树的每个点有一个颜色 Ci。</p><p>如果一棵树中存在的每种颜色的结点个数都相同,则我们称它是一棵颜色平衡树。</p><p>求出这棵树中有多少个子树是颜色平衡树。</p></li><li><p>思路:dfs深度递归每一棵树,先cnt(u)(x) = p,表示根节点为u的子树颜色为x的有p个,然后sum(u)(cnt(u)(k)) = q表示以u为根节点的子树下颜色个数为cnt(u)(k)的有q组,如果最终sum(u)的大小为1,表示所有颜色的个数都是相同的。cnt和sum都是三维结构,采用unordered_map存储。</p></li><li><p>代码:</p></li></ul><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-type">const</span> <span class="hljs-type">int</span> N = <span class="hljs-number">2e5</span> + <span class="hljs-number">10</span>;<br><span class="hljs-type">int</span> n, c[N], ans;<br>vector<<span class="hljs-type">int</span>> g[N];<br>unordered_map<<span class="hljs-type">int</span>, <span class="hljs-type">int</span>> cnt[N], sum[N];<br><span class="hljs-function"><span class="hljs-type">void</span> <span class="hljs-title">dfs</span><span class="hljs-params">(<span class="hljs-type">int</span> u)</span></span>{<br>cnt[u][c[u]] = <span class="hljs-number">1</span>;<br>sum[u][<span class="hljs-number">1</span>] = <span class="hljs-number">1</span>;<br><span class="hljs-keyword">for</span>(<span class="hljs-keyword">auto</span> &v : g[u]){<br><span class="hljs-built_in">dfs</span>(v);<br><span class="hljs-keyword">for</span>(<span class="hljs-keyword">auto</span> &it : cnt[v]){<br><span class="hljs-type">int</span> x = it.first, y = it.second;<br><span class="hljs-keyword">if</span>(cnt[u].<span class="hljs-built_in">count</span>(x)){<br>sum[u][cnt[u][x]]--;<br><span class="hljs-keyword">if</span>(sum[u][cnt[u][x]] == <span class="hljs-number">0</span>){<br>sum[u].<span class="hljs-built_in">erase</span>(cnt[u][x]);<br>}<br>}<br>sum[u][cnt[u][x]+=y]++;<br>}<br>}<br><span class="hljs-keyword">if</span>(sum[u].<span class="hljs-built_in">size</span>() == <span class="hljs-number">1</span>) ans++;<br>}<br><span class="hljs-function"><span class="hljs-type">int</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br>cin>>n;<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>, x; i <= n; i++){<br>cin >> c[i] >> x;<br>g[x].<span class="hljs-built_in">emplace_back</span>(i);<br>}<br><span class="hljs-built_in">dfs</span>(<span class="hljs-number">1</span>);<br>cout<<ans; <br><br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:很厉害的写法,尤其是sum的增加使得原先需要遍历所有的cnt判断颜色个数是否一致可以O(1)的时间复杂度判断出来,而对sum的递推是直接内嵌在dfs里的,太厉害了。还有unordered_map对于三维数组的应用也非常熟练,太厉害了!而且这个dfs也没有一般的终结条件,即叶节点,相当于隐式的方式了。很棒的一道题,考场上要是能模拟出这种暴力真的就太棒了!~</li></ul><h3 id="G网络稳定性:"><a href="#G网络稳定性:" class="headerlink" title="G网络稳定性:"></a>G网络稳定性:</h3><figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br></pre></td><td class="code"><pre><code class="hljs c++"><span class="hljs-meta">#<span class="hljs-keyword">include</span><span class="hljs-string"><bits/stdc++.h></span></span><br><span class="hljs-keyword">using</span> <span class="hljs-keyword">namespace</span> std;<br><span class="hljs-meta">#<span class="hljs-keyword">define</span> int long long</span><br><span class="hljs-type">int</span> dp[<span class="hljs-number">5005</span>][<span class="hljs-number">5005</span>]; <br><span class="hljs-type">int</span> n, m, q;<br><span class="hljs-function"><span class="hljs-type">signed</span> <span class="hljs-title">main</span><span class="hljs-params">()</span></span><br><span class="hljs-function"></span>{<br><span class="hljs-built_in">memset</span>(dp,<span class="hljs-number">-1</span>,<span class="hljs-built_in">sizeof</span>(dp));<br>cin>>n>>m>>q;<br><span class="hljs-type">int</span> u,v,x;<br><span class="hljs-keyword">while</span>(m--){<br>cin>>u>>v>>x;<br>dp[u][v] = <span class="hljs-built_in">max</span>(dp[u][v], x);<br>dp[v][u] = <span class="hljs-built_in">max</span>(dp[v][u], x);<br>}<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> k = <span class="hljs-number">1</span>; k <= n; k++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> i = <span class="hljs-number">1</span>; i <= n ;i++){<br><span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> j = <span class="hljs-number">1</span>; j <= n; j++){<br><span class="hljs-keyword">if</span>(i != j && i != k && j != k){<br>dp[i][j] = <span class="hljs-built_in">max</span>(dp[i][j], <span class="hljs-built_in">min</span>(dp[i][k],dp[k][j]));<br>}<br>}<br>}<br>}<br><span class="hljs-keyword">while</span>(q--){<br>cin>>u>>v;<br>cout<<dp[u][v]<<endl;<br>}<br><span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br>}<br></code></pre></td></tr></table></figure>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>蓝桥杯</tag>
</tags>
</entry>
<entry>
<title>力扣链表部分题目总结---基本完结~</title>
<link href="/2024/02/02/%E5%8A%9B%E6%89%A3%E7%AE%97%E6%B3%95%E9%A2%98/%E5%8A%9B%E6%89%A3%E9%93%BE%E8%A1%A8%E9%83%A8%E5%88%86%E9%A2%98%E7%9B%AE%E6%80%BB%E7%BB%93/"/>
<url>/2024/02/02/%E5%8A%9B%E6%89%A3%E7%AE%97%E6%B3%95%E9%A2%98/%E5%8A%9B%E6%89%A3%E9%93%BE%E8%A1%A8%E9%83%A8%E5%88%86%E9%A2%98%E7%9B%AE%E6%80%BB%E7%BB%93/</url>
<content type="html"><![CDATA[<h2 id="链表"><a href="#链表" class="headerlink" title="链表"></a>链表</h2><h3 id="前言:"><a href="#前言:" class="headerlink" title="前言:"></a>前言:</h3><p>链表部分之前刷力扣也做过一些,基本做不出来,都是看题解,希望这次训练可以在链表的题目上有些进步叭;)</p><h3 id="1-相交链表"><a href="#1-相交链表" class="headerlink" title="1.相交链表"></a>1.相交链表</h3><ul><li>描述:给你两个单链表的头节点 <code>headA</code> 和 <code>headB</code> ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 <code>null</code> 。</li></ul><h4 id="解法一:"><a href="#解法一:" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:两个链表相交,采用双指针的方法,开始分别指向两个链表头,同步向后走,一旦走完一个链表就换另一个链表头继续走,那么两个指针会在相交位置刚好重逢(如果相交的话),否则就返回null。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">getIntersectionNode</span><span class="hljs-params">(ListNode headA, ListNode headB)</span> {<br> <span class="hljs-keyword">if</span>(headA == <span class="hljs-literal">null</span> || headB == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">pA</span> <span class="hljs-operator">=</span> headA;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">pB</span> <span class="hljs-operator">=</span> headB;<br> <span class="hljs-keyword">while</span>(pA != pB){<br> pA = pA == <span class="hljs-literal">null</span>? headB : pA.next;<br> pB = pB == <span class="hljs-literal">null</span>? headA : pB.next;<br> }<br> <span class="hljs-keyword">return</span> pA;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>非常巧妙的双指针,简洁有力的解决问题。简写的条件判断自己写的话用的比较少,可以学习一下。</li></ul><h4 id="解法二:"><a href="#解法二:" class="headerlink" title="解法二:"></a>解法二:</h4><ul><li>思路:用哈希表存下一个链表的所有节点,再遍历另一个链表去找相交点,由于哈希表里存的是地址,所以是可行的。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">getIntersectionNode</span><span class="hljs-params">(ListNode headA, ListNode headB)</span> {<br> Set<ListNode> visited = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashSet</span><>();<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">tmp</span> <span class="hljs-operator">=</span> headA;<br> <span class="hljs-keyword">while</span>(tmp != <span class="hljs-literal">null</span>){<br> visited.add(tmp);<br> tmp = tmp.next;<br> }<br> tmp = headB;<br> <span class="hljs-keyword">while</span>(tmp != <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">if</span>(visited.contains(tmp)){<br> <span class="hljs-keyword">return</span> tmp;<br> }<br> tmp = tmp.next;<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:思路并不难,就是对Set这些数据结构要足够熟悉才行。</li></ul><h3 id="2-反转链表"><a href="#2-反转链表" class="headerlink" title="2.反转链表"></a>2.反转链表</h3><ul><li>描述:给你单链表的头节点 <code>head</code> ,请你反转链表,并返回反转后的链表。</li></ul><h4 id="解法一:-1"><a href="#解法一:-1" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:采用迭代的方式,设置3个变量prev,cur,next,从链表头开始逐步反转每一条next指针</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">reverseList</span><span class="hljs-params">(ListNode head)</span> {<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">prev</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">cur</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-keyword">while</span>(cur != <span class="hljs-literal">null</span>){<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">next</span> <span class="hljs-operator">=</span> cur.next;<br> cur.next = prev;<br> prev = cur;<br> cur = next;<br> }<br> <span class="hljs-keyword">return</span> prev;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:最直白的思路,但是还是要对链表的基础足够熟悉才行。</li></ul><h4 id="解法二:-1"><a href="#解法二:-1" class="headerlink" title="解法二:"></a>解法二:</h4><ul><li>思路:采取递归,一直往后,那么假设后半段链表已经反转过来,形成类似O->O-><strong>O->O</strong><-O<-O,那么中间这个的前一个head的next.next修改为自己,再head.next=null,即可变为O->O-><strong>O<-O</strong><-O<-O,以此类推。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">reverseList</span><span class="hljs-params">(ListNode head)</span> {<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span> || head.next == <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">return</span> head;<br> }<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">newHead</span> <span class="hljs-operator">=</span> reverseList(head.next);<br> head.next.next = head;<br> head.next = <span class="hljs-literal">null</span>;<br> <span class="hljs-keyword">return</span> newHead;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:递归更加抽象,也更加有意思,对于递归的处理有了更深的理解,一般都是倒推,后面的已经完成,怎么处理当前的状况。</li></ul><h3 id="3-回文链表:"><a href="#3-回文链表:" class="headerlink" title="3.回文链表:"></a>3.回文链表:</h3><ul><li>描述:给你一个单链表的头节点 <code>head</code> ,请你判断该链表是否为回文链表。如果是,返回 <code>true</code> ;否则,返回 <code>false</code> 。</li></ul><h4 id="解法一:-2"><a href="#解法一:-2" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:用一个数组取出所有节点的val,然后双指针判断是否回文</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isPalindrome</span><span class="hljs-params">(ListNode head)</span> {<br> List<Integer> vals = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><>();<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">cur</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-keyword">while</span>(cur != <span class="hljs-literal">null</span>){<br> vals.add(cur.val);<br> cur = cur.next;<br> }<br> <span class="hljs-type">int</span> <span class="hljs-variable">l</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>, r = vals.size() - <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">while</span>(l < r){<br> <span class="hljs-keyword">if</span>(!vals.get(l).equals(vals.get(r))){<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> }<br> l++;<br> r--;<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:最直接的思路,熟练使用List数据结构,包括add,get,equals方法。</li></ul><h4 id="解法二:-2"><a href="#解法二:-2" class="headerlink" title="解法二:"></a>解法二:</h4><ul><li>思路:利用递归会变相的反向遍历链表这个特点,设置一个从head开始的全局变量进行比较验证。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">private</span> ListNode frontPointer;<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">recursivelyCheck</span><span class="hljs-params">(ListNode cur)</span>{<br> <span class="hljs-keyword">if</span>(cur == <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> }<br> <span class="hljs-keyword">if</span>(!recursivelyCheck(cur.next)){<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> }<br> <span class="hljs-keyword">if</span>(cur.val == frontPointer.val){<br> frontPointer = frontPointer.next;<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isPalindrome</span><span class="hljs-params">(ListNode head)</span> {<br> frontPointer = head;<br> <span class="hljs-keyword">return</span> recursivelyCheck(head);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:实用性不强,因为在许多语言中,堆栈帧的开销很大(如 Python),并且最大的运行时堆栈深度为 1000(可以增加,但是有可能导致底层解释程序内存出错)。为每个节点创建堆栈帧极大的限制了算法能够处理的最大链表大小。但是思路很有意思。</li></ul><h4 id="解法三:"><a href="#解法三:" class="headerlink" title="解法三:"></a>解法三:</h4><ul><li>思路:为了实现O(1)的空间复杂度,先利用快慢指针找到链表的中间位置,返回后半部分链表,比较两个链表,再恢复链表。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">endOfFisrtHalf</span><span class="hljs-params">(ListNode head)</span>{<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">slow</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">fast</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-keyword">while</span>(fast.next != <span class="hljs-literal">null</span> && fast.next.next != <span class="hljs-literal">null</span>){ <span class="hljs-comment">//考虑只有一个节点或两个节点的特殊情况,最终slow必须是属于前半部分的最后一个节点</span><br> fast = fast.next.next;<br> slow = slow.next;<br> }<br> <span class="hljs-keyword">return</span> slow;<br> }<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">reverseList</span><span class="hljs-params">(ListNode head)</span> {<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">prev</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">cur</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-keyword">while</span>(cur != <span class="hljs-literal">null</span>){<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">next</span> <span class="hljs-operator">=</span> cur.next;<br> cur.next = prev;<br> prev = cur;<br> cur = next;<br> }<br> <span class="hljs-keyword">return</span> prev;<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isPalindrome</span><span class="hljs-params">(ListNode head)</span> {<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">firstHalfEnd</span> <span class="hljs-operator">=</span> endOfFisrtHalf(head);<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">secondHalfStart</span> <span class="hljs-operator">=</span> reverseList(firstHalfEnd.next);<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">p1</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">p2</span> <span class="hljs-operator">=</span> secondHalfStart;<br> <span class="hljs-type">boolean</span> <span class="hljs-variable">res</span> <span class="hljs-operator">=</span> <span class="hljs-literal">true</span>;<br> <span class="hljs-keyword">while</span>(res && p2 != <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">if</span>(p1.val != p2.val){<br> res = <span class="hljs-literal">false</span>;<br> }<br> p1 = p1.next;<br> p2 = p2.next;<br> }<br> firstHalfEnd.next = reverseList(secondHalfStart);<br> <span class="hljs-keyword">return</span> res;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:和之前的反转链表连起来了,很美妙的做法,以及通过快慢指针找中间节点的方法,感觉也很常用。</li></ul><h3 id="4-环形链表"><a href="#4-环形链表" class="headerlink" title="4.环形链表"></a>4.环形链表</h3><ul><li><p>描述:给你一个链表的头节点 <code>head</code> ,判断链表中是否有环。</p><p><em>如果链表中存在环</em> ,则返回 <code>true</code> 。 否则,返回 <code>false</code> 。</p></li></ul><h4 id="解法一:-3"><a href="#解法一:-3" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:利用快慢指针,慢指针一次走一步,快指针一次走两步,如果有环,那么快指针一定比慢指针先进入,继而落后于慢指针,由于<strong>此时快指针与慢指针的距离每次减少1</strong>,<strong>环可以看作是无限的直线,所以一定会相遇</strong>。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">hasCycle</span><span class="hljs-params">(ListNode head)</span> {<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span> || head.next == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">slow</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">fast</span> <span class="hljs-operator">=</span> head.next;<br> <span class="hljs-keyword">while</span>(slow != fast){<br> <span class="hljs-keyword">if</span>(fast == <span class="hljs-literal">null</span> || fast.next == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> slow = slow.next;<br> fast = fast.next.next;<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:神奇的快慢指针,与环结合很适合用来做相遇,很棒的思路~</li></ul><h3 id="5-环形链表"><a href="#5-环形链表" class="headerlink" title="5.环形链表||"></a>5.环形链表||</h3><ul><li>描述:给定一个链表的头节点 <code>head</code> ,返回链表开始入环的第一个节点。 <em>如果链表无环,则返回 <code>null</code>。</em></li></ul><h4 id="解法一:-4"><a href="#解法一:-4" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li><p>思路:回归最简单直接的方法,Hash记录所有访问过的点,一旦再次访问到即可直接返回。</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">detectCycle</span><span class="hljs-params">(ListNode head)</span> {<br> Set<ListNode> visited = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashSet</span><>();<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">pos</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-keyword">while</span>(pos != <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">if</span>(visited.contains(pos)){<br> <span class="hljs-keyword">return</span> pos;<br> }<span class="hljs-keyword">else</span>{<br> visited.add(pos);<br> pos = pos.next;<br> }<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><h4 id="解法二:-3"><a href="#解法二:-3" class="headerlink" title="解法二:"></a>解法二:</h4><img src="00.png" alt="思路" width="500px"><ul><li>思路:还是基于快慢指针,并且通过数学计算发现相遇后,从头节点到入环点的距离等于相遇点到入环点的距离。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">detectCycle</span><span class="hljs-params">(ListNode head)</span> {<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span> || head.next == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">slow</span> <span class="hljs-operator">=</span> head, fast = head;<br> <span class="hljs-keyword">while</span>(fast != <span class="hljs-literal">null</span>){<br> slow = slow.next;<br> <span class="hljs-keyword">if</span>(fast.next == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> fast = fast.next.next;<br> <span class="hljs-keyword">if</span>(slow == fast){<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">ptr</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-keyword">while</span>(ptr != slow){<br> ptr = ptr.next;<br> slow = slow.next;<br> }<br> <span class="hljs-keyword">return</span> ptr;<br> }<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:和直接判断环的题目还是不太一样,首先就是快慢指针的起点都是head,然后导致while判断也发生变化,需要视情况而定。</li></ul><h3 id="6-合并两个有序链表"><a href="#6-合并两个有序链表" class="headerlink" title="6.合并两个有序链表"></a>6.合并两个有序链表</h3><ul><li>描述:将两个升序链表合并为一个新的 <strong>升序</strong> 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。</li></ul><h4 id="解法一:-5"><a href="#解法一:-5" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:采用递归的思想,先判断两个头部的值,较小的保留,剩余的两个链表继续合并,直到其中一个链表为空。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">mergeTwoLists</span><span class="hljs-params">(ListNode list1, ListNode list2)</span> {<br> <span class="hljs-keyword">if</span>(list1 == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> list2;<br> <span class="hljs-keyword">if</span>(list2 == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> list1;<br> <span class="hljs-keyword">if</span>(list1.val < list2.val){<br> list1.next = mergeTwoLists(list1.next, list2);<br> <span class="hljs-keyword">return</span> list1;<br> }<span class="hljs-keyword">else</span>{<br> list2.next = mergeTwoLists(list1, list2.next);<br> <span class="hljs-keyword">return</span> list2;<br> }<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:两种情况再分别递归,实现两个链表中的较小值的逐一合并,很巧妙。</li></ul><h3 id="7-两数相加"><a href="#7-两数相加" class="headerlink" title="7.两数相加"></a>7.两数相加</h3><ul><li>描述:给你两个 <strong>非空</strong> 的链表,表示两个非负的整数。它们每位数字都是按照 <strong>逆序</strong> 的方式存储的,并且每个节点只能存储 <strong>一位</strong> 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字 0 之外,这两个数都不会以 0 开头。</li></ul><h4 id="解法一:-6"><a href="#解法一:-6" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li><p>思路:创建一个新链,逐个去取两个链表上的数相加,直到两个链表均为空,若有一个为空,直接赋值为0,最后注意还要判断一下进位。</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">addTwoNumbers</span><span class="hljs-params">(ListNode l1, ListNode l2)</span> {<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">head</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>, tail = <span class="hljs-literal">null</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">carry</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">while</span>(l1 != <span class="hljs-literal">null</span> || l2!= <span class="hljs-literal">null</span>){<br> <span class="hljs-type">int</span> <span class="hljs-variable">n1</span> <span class="hljs-operator">=</span> l1 != <span class="hljs-literal">null</span> ? l1.val : <span class="hljs-number">0</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">n2</span> <span class="hljs-operator">=</span> l2 != <span class="hljs-literal">null</span> ? l2.val : <span class="hljs-number">0</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">sum</span> <span class="hljs-operator">=</span> n1 + n2 + carry;<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span>){<br> head = tail = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ListNode</span>(sum % <span class="hljs-number">10</span>);<br> }<span class="hljs-keyword">else</span>{<br> tail.next = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ListNode</span>(sum % <span class="hljs-number">10</span>);<br> tail = tail.next;<br> }<br> carry = sum /<span class="hljs-number">10</span>;<br> <span class="hljs-keyword">if</span>(l1 != <span class="hljs-literal">null</span>){<br> l1 = l1.next;<br> }<br> <span class="hljs-keyword">if</span>(l2 != <span class="hljs-literal">null</span>){<br> l2 = l2.next;<br> } <br> }<br> <span class="hljs-keyword">if</span>(carry > <span class="hljs-number">0</span>){<br> tail.next = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ListNode</span>(carry);<br> }<br> <span class="hljs-keyword">return</span> head;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:思路很清晰,主要是写代码要多多注意细节问题~</li></ul><h3 id="8-排序链表"><a href="#8-排序链表" class="headerlink" title="8.排序链表"></a>8.排序链表</h3><ul><li>描述:给你链表的头结点 <code>head</code> ,请将其按 <strong>升序</strong> 排列并返回 <strong>排序后的链表</strong> 。</li></ul><h4 id="解法一:-7"><a href="#解法一:-7" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:<strong>自顶向下</strong>,采用归并递归的方法,不断细分链表,直到不能再细分然后进行合并两个有序链表。时间复杂度为O(NlogN),空间复杂度为O(NlogN),因为用到了栈的递归空间。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">sortList</span><span class="hljs-params">(ListNode head)</span> {<br> <span class="hljs-keyword">return</span> sortList(head, <span class="hljs-literal">null</span>);<br> }<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">sortList</span><span class="hljs-params">(ListNode head, ListNode tail)</span>{<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> head; <span class="hljs-comment">//当前链表没有节点或只有一个节点是返回条件</span><br> <span class="hljs-keyword">if</span>(head.next == tail){<br> head.next = <span class="hljs-literal">null</span>;<br> <span class="hljs-keyword">return</span> head;<br> }<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">slow</span> <span class="hljs-operator">=</span> head, fast = head;<br> <span class="hljs-keyword">while</span>(fast != tail){<br> slow = slow.next;<br> fast = fast.next;<br> <span class="hljs-keyword">if</span>(fast != tail){<br> fast = fast.next;<br> }<br> }<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">mid</span> <span class="hljs-operator">=</span> slow;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">list1</span> <span class="hljs-operator">=</span> sortList(head, mid);<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">list2</span> <span class="hljs-operator">=</span> sortList(mid, tail);<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">sorted</span> <span class="hljs-operator">=</span> merge(list1, list2);<br> <span class="hljs-keyword">return</span> sorted;<br> }<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">merge</span><span class="hljs-params">(ListNode head1, ListNode head2)</span>{<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">dummyHead</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ListNode</span>(<span class="hljs-number">0</span>);<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">tmp1</span> <span class="hljs-operator">=</span> head1, tmp2 = head2;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">temp</span> <span class="hljs-operator">=</span> dummyHead;<br> <span class="hljs-keyword">while</span>(tmp1 != <span class="hljs-literal">null</span> && tmp2 != <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">if</span>(tmp1.val <= tmp2.val){<br> temp.next = tmp1;<br> tmp1 = tmp1.next;<br> }<span class="hljs-keyword">else</span>{<br> temp.next = tmp2;<br> tmp2 = tmp2.next;<br> }<br> temp = temp.next;<br> }<br> <span class="hljs-keyword">if</span>(tmp1 != <span class="hljs-literal">null</span>){<br> temp.next = tmp1;<br> }<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(tmp2 != <span class="hljs-literal">null</span>){<br> temp.next = tmp2;<br> }<br> <span class="hljs-keyword">return</span> dummyHead.next;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:关键点就是归并实现最终的排序,一些细节问题需要注意,比如需要断链然后再重新合并(tail这个节点很关键),merge方法还要更加熟练。</li></ul><h4 id="解法二:-4"><a href="#解法二:-4" class="headerlink" title="解法二:"></a>解法二:</h4><ul><li>思路:<strong>自底向上</strong>,先把链表分为subLen为1的子链表,两两合并,subLen再乘2重复操作,直到大于等于链表长度。涉及到两个子链表的拆分(cur)然后再合并(prev),细节要很清楚才行。时间复杂度为O(NlogN),<strong>空间复杂度为O(1)</strong>.</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">sortList</span><span class="hljs-params">(ListNode head)</span> {<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">dummyHead</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ListNode</span>(<span class="hljs-number">0</span>);<br> dummyHead.next = head;<br> <span class="hljs-type">int</span> <span class="hljs-variable">len</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">node</span> <span class="hljs-operator">=</span> head;<br> <span class="hljs-keyword">while</span>(node != <span class="hljs-literal">null</span>){<br> len++;<br> node = node.next;<br> }<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> <span class="hljs-variable">subLen</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>; subLen < len; subLen <<= <span class="hljs-number">1</span>){<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">prev</span> <span class="hljs-operator">=</span> dummyHead;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">cur</span> <span class="hljs-operator">=</span> dummyHead.next;<br> <span class="hljs-keyword">while</span>(cur != <span class="hljs-literal">null</span>){<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">head_1</span> <span class="hljs-operator">=</span> cur;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>; i < subLen && cur != <span class="hljs-literal">null</span> && cur.next != <span class="hljs-literal">null</span>; i++){<br> cur = cur.next;<br> }<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">head_2</span> <span class="hljs-operator">=</span> cur.next;<br> cur.next = <span class="hljs-literal">null</span>;<br> cur = head_2;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>; i < subLen && cur != <span class="hljs-literal">null</span> && cur.next != <span class="hljs-literal">null</span>; i++){<br> cur = cur.next;<br> }<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">next</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-keyword">if</span>(cur != <span class="hljs-literal">null</span>){<br> next = cur.next;<br> cur.next = <span class="hljs-literal">null</span>;<br> }<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">merged</span> <span class="hljs-operator">=</span> merge(head_1, head_2);<br> prev.next = merged;<br> <span class="hljs-keyword">while</span>(prev.next != <span class="hljs-literal">null</span>){<br> prev = prev.next;<br> }<br> cur = next;<br> }<br> }<br> <span class="hljs-keyword">return</span> dummyHead.next;<br> }<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">merge</span><span class="hljs-params">(ListNode head1, ListNode head2)</span>{<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">dummyHead</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ListNode</span>(<span class="hljs-number">0</span>);<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">tmp1</span> <span class="hljs-operator">=</span> head1, tmp2 = head2;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">temp</span> <span class="hljs-operator">=</span> dummyHead;<br> <span class="hljs-keyword">while</span>(tmp1 != <span class="hljs-literal">null</span> && tmp2 != <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">if</span>(tmp1.val <= tmp2.val){<br> temp.next = tmp1;<br> tmp1 = tmp1.next;<br> }<span class="hljs-keyword">else</span>{<br> temp.next = tmp2;<br> tmp2 = tmp2.next;<br> }<br> temp = temp.next;<br> }<br> <span class="hljs-keyword">if</span>(tmp1 != <span class="hljs-literal">null</span>){<br> temp.next = tmp1;<br> }<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span>(tmp2 != <span class="hljs-literal">null</span>){<br> temp.next = tmp2;<br> }<br> <span class="hljs-keyword">return</span> dummyHead.next;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:这是一道很棒的题目,深入熟悉了两种做法,特别是两种优秀的底层思路,归并和自底向上。自底向上的思路说起来简单,但是操作起来常常有很多细节需要反复推敲,熟能生巧叭~</li></ul><h3 id="9-两两交换链表中的节点"><a href="#9-两两交换链表中的节点" class="headerlink" title="9.两两交换链表中的节点"></a>9.两两交换链表中的节点</h3><ul><li>描述:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)</li></ul><h4 id="解法一:-8"><a href="#解法一:-8" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:本质就是交换链表中的两个节点,然后采取递归的方式不断往后走。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">swapPairs</span><span class="hljs-params">(ListNode head)</span> {<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span> || head.next == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> head;<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">newHead</span> <span class="hljs-operator">=</span> head.next;<br> head.next = newHead.next;<br> newHead.next = head;<br> head.next = swapPairs(head.next);<br> <span class="hljs-keyword">return</span> newHead;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:自己写出来的一道题目,很棒,刚开始swapPairs里写成了head.next.next,然后根据输出debug解决了问题,很不错~</li></ul><h3 id="10-随机链表的复制"><a href="#10-随机链表的复制" class="headerlink" title="10.随机链表的复制"></a>10.随机链表的复制</h3><ul><li>描述:给你一个长度为 <code>n</code> 的链表,每个节点包含一个额外增加的随机指针 <code>random</code> ,该指针可以指向链表中的任何节点或空节点。构造这个链表的 <strong><a href="https://baike.baidu.com/item/%E6%B7%B1%E6%8B%B7%E8%B4%9D/22785317?fr=aladdin">深拷贝</a><strong>。 深拷贝应该正好由 <code>n</code> 个 <strong>全新</strong> 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 <code>next</code> 指针和 <code>random</code> 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。</strong>复制链表中的指针都不应指向原链表中的节点</strong> 。</li></ul><h4 id="解法一:-9"><a href="#解法一:-9" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:由于random指针可能指向后面的未创建的节点,所以采用<strong>回溯+哈希表</strong>,直接往下递归,把对应的节点返回来即可。时间和空间复杂度都是O(N)。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> Map<Node, Node> cacheNode = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><>();<br> <span class="hljs-keyword">public</span> Node <span class="hljs-title function_">copyRandomList</span><span class="hljs-params">(Node head)</span> {<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-keyword">if</span>(!cacheNode.containsKey(head)){<br> <span class="hljs-type">Node</span> <span class="hljs-variable">newNode</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Node</span>(head.val);<br> cacheNode.put(head, newNode);<br> newNode.next = copyRandomList(head.next);<br> newNode.random = copyRandomList(head.random);<br> }<br> <span class="hljs-keyword">return</span> cacheNode.get(head);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:原来<strong>递归还可以用于回溯</strong>,其实好像递归的本质就有点回溯的意味,那么这道题刚好应用了这一本质,再结合哈希避免了节点的重复复制。</li></ul><h4 id="解法二:-5"><a href="#解法二:-5" class="headerlink" title="解法二:"></a>解法二:</h4><ul><li>思路:采取<strong>迭代</strong>的方法,先把每个节点拆分为两个一样的节点,前面一个节点作为原节点,后面一个节点作为复制节点,遍历把后面节点的random指针指向对应的复制节点,最后再<strong>拆分链表</strong>。时间复杂度为O(N),空间复杂度为O(1)。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> Node <span class="hljs-title function_">copyRandomList</span><span class="hljs-params">(Node head)</span> {<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">Node</span> <span class="hljs-variable">node</span> <span class="hljs-operator">=</span> head; node != <span class="hljs-literal">null</span>; node = node.next.next){<br> <span class="hljs-type">Node</span> <span class="hljs-variable">newNode</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">Node</span>(node.val);<br> newNode.next = node.next;<br> node.next = newNode;<br> }<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">Node</span> <span class="hljs-variable">node</span> <span class="hljs-operator">=</span> head; node != <span class="hljs-literal">null</span>; node = node.next.next){<br> <span class="hljs-type">Node</span> <span class="hljs-variable">newNode</span> <span class="hljs-operator">=</span> node.next;<br> newNode.random = (node.random != <span class="hljs-literal">null</span>) ? node.random.next : <span class="hljs-literal">null</span>;<br> }<br> <span class="hljs-type">Node</span> <span class="hljs-variable">newHead</span> <span class="hljs-operator">=</span> head.next;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">Node</span> <span class="hljs-variable">node</span> <span class="hljs-operator">=</span> head; node != <span class="hljs-literal">null</span>; node = node.next){<br> <span class="hljs-type">Node</span> <span class="hljs-variable">newNode</span> <span class="hljs-operator">=</span> node.next;<br> node.next = node.next.next;<br> newNode.next = (newNode.next != <span class="hljs-literal">null</span>) ? newNode.next.next : <span class="hljs-literal">null</span>;<br> }<br> <span class="hljs-keyword">return</span> newHead;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:由于链表的特性采取复制节点的想法,那么next指针的复制就很自然,random指针的复制也很方便,很巧妙的方法~</li></ul><h4 id="解法三:-1"><a href="#解法三:-1" class="headerlink" title="解法三:"></a>解法三:</h4><ul><li>思路:直接先忽略random指针复制出链表的结构,然后再针对random指针进行复制即可。其中利用<strong>map</strong>键值对来维护节点和它的复制节点的关系。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> Node <span class="hljs-title function_">copyRandomList</span><span class="hljs-params">(Node head)</span> {<br> <span class="hljs-keyword">if</span>(head == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-type">Node</span> <span class="hljs-variable">cur</span> <span class="hljs-operator">=</span> head;<br> Map<Node, Node> map = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><>();<br> <span class="hljs-keyword">while</span>(cur != <span class="hljs-literal">null</span>){<br> map.put(cur, <span class="hljs-keyword">new</span> <span class="hljs-title class_">Node</span>(cur.val));<br> cur = cur.next;<br> }<br> cur = head;<br> <span class="hljs-keyword">while</span>(cur != <span class="hljs-literal">null</span>){<br> map.get(cur).next = map.get(cur.next);<br> map.get(cur).random = map.get(cur.random);<br> cur = cur.next;<br> }<br> <span class="hljs-keyword">return</span> map.get(head);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:超级简单易懂,巧妙地采取了Map来维护,非常巧妙!</li></ul><h3 id="11-LRU缓存"><a href="#11-LRU缓存" class="headerlink" title="11.LRU缓存"></a>11.LRU缓存</h3><ul><li><p>描述:请你设计并实现一个满足 <a href="https://baike.baidu.com/item/LRU">LRU (最近最少使用) 缓存</a> 约束的数据结构。</p><p>实现 <code>LRUCache</code> 类:</p><ul><li><code>LRUCache(int capacity)</code> 以 <strong>正整数</strong> 作为容量 <code>capacity</code> 初始化 LRU 缓存</li><li><code>int get(int key)</code> 如果关键字 <code>key</code> 存在于缓存中,则返回关键字的值,否则返回 <code>-1</code> 。</li><li><code>void put(int key, int value)</code> 如果关键字 <code>key</code> 已经存在,则变更其数据值 <code>value</code> ;如果不存在,则向缓存中插入该组 <code>key-value</code> 。如果插入操作导致关键字数量超过 <code>capacity</code> ,则应该 <strong>逐出</strong> 最久未使用的关键字。</li></ul><p>函数 <code>get</code> 和 <code>put</code> 必须以 <code>O(1)</code> 的平均时间复杂度运行。</p></li></ul><h4 id="解法一:-10"><a href="#解法一:-10" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:采用map来实现key和node的对应,采用双向链表来维护节点间的结构,保证了删除尾节点后在O(1)时间内找到尾结点的前一个作为新的尾结点。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">LRUCache</span> {<br> <span class="hljs-keyword">class</span> <span class="hljs-title class_">DLinkedNode</span>{<br> <span class="hljs-type">int</span> key;<br> <span class="hljs-type">int</span> value;<br> DLinkedNode prev;<br> DLinkedNode next;<br> <span class="hljs-keyword">public</span> <span class="hljs-title function_">DLinkedNode</span><span class="hljs-params">()</span>{}<br> <span class="hljs-keyword">public</span> <span class="hljs-title function_">DLinkedNode</span><span class="hljs-params">(<span class="hljs-type">int</span> _key, <span class="hljs-type">int</span> _value)</span>{<br> key = _key;<br> value = _value;<br> }<br> }<br> <span class="hljs-keyword">private</span> Map<Integer, DLinkedNode> cache = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><>();<br> <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> size;<br> <span class="hljs-keyword">private</span> <span class="hljs-type">int</span> capacity;<br> <span class="hljs-keyword">private</span> DLinkedNode head, tail;<br> <span class="hljs-keyword">public</span> <span class="hljs-title function_">LRUCache</span><span class="hljs-params">(<span class="hljs-type">int</span> capacity)</span> {<br> <span class="hljs-built_in">this</span>.size = <span class="hljs-number">0</span>;<br> <span class="hljs-built_in">this</span>.capacity = capacity;<br> head = <span class="hljs-keyword">new</span> <span class="hljs-title class_">DLinkedNode</span>();<br> tail = <span class="hljs-keyword">new</span> <span class="hljs-title class_">DLinkedNode</span>();<br> head.next = tail;<br> tail.prev = head;<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">get</span><span class="hljs-params">(<span class="hljs-type">int</span> key)</span> {<br> <span class="hljs-type">DLinkedNode</span> <span class="hljs-variable">node</span> <span class="hljs-operator">=</span> cache.get(key);<br> <span class="hljs-keyword">if</span>(node == <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">return</span> -<span class="hljs-number">1</span>;<br> }<br> moveToHead(node);<br> <span class="hljs-keyword">return</span> node.value;<br> }<br> <br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">put</span><span class="hljs-params">(<span class="hljs-type">int</span> key, <span class="hljs-type">int</span> value)</span> {<br> <span class="hljs-type">DLinkedNode</span> <span class="hljs-variable">node</span> <span class="hljs-operator">=</span> cache.get(key);<br> <span class="hljs-keyword">if</span>(node == <span class="hljs-literal">null</span>){<br> <span class="hljs-type">DLinkedNode</span> <span class="hljs-variable">newNode</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">DLinkedNode</span>(key, value);<br> cache.put(key, newNode);<br> addToHead(newNode);<br> size++;<br> <span class="hljs-keyword">if</span>(size > capacity){<br> <span class="hljs-type">DLinkedNode</span> <span class="hljs-variable">tail</span> <span class="hljs-operator">=</span> removeTail();<br> cache.remove(tail.key);<br> size--;<br> }<br> }<span class="hljs-keyword">else</span>{<br> node.value = value;<br> moveToHead(node);<br> }<br> }<br> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">moveToHead</span><span class="hljs-params">(DLinkedNode node)</span>{<br> removeNode(node);<br> addToHead(node);<br> }<br> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">removeNode</span><span class="hljs-params">(DLinkedNode node)</span>{<br> node.prev.next = node.next;<br> node.next.prev = node.prev;<br> }<br> <span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">addToHead</span><span class="hljs-params">(DLinkedNode node)</span>{<br> node.next = head.next;<br> node.prev = head;<br> head.next.prev = node;<br> head.next = node;<br> }<br> <span class="hljs-keyword">private</span> DLinkedNode <span class="hljs-title function_">removeTail</span><span class="hljs-params">()</span>{<br> <span class="hljs-type">DLinkedNode</span> <span class="hljs-variable">res</span> <span class="hljs-operator">=</span> tail.prev;<br> removeNode(res);<br> <span class="hljs-keyword">return</span> res;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:对于链表来说很好的一道综合题,考察了各种链表操作。然后双向链表以及head,tail节点的使用也很精妙,值得反复去写的一道题。</li></ul><h3 id="12-K个一组翻转链表"><a href="#12-K个一组翻转链表" class="headerlink" title="12.K个一组翻转链表"></a>12.K个一组翻转链表</h3><ul><li><p>描述: 给你链表的头节点 <code>head</code> ,每 <code>k</code> 个节点一组进行翻转,请你返回修改后的链表。</p><p><code>k</code> 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 <code>k</code> 的整数倍,那么请将最后剩余的节点保持原有顺序。</p><p>你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换</p></li></ul><h4 id="解法一"><a href="#解法一" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路: 对每k个节点进行翻转链表,由于是翻转部分链表,那么链表的<strong>两侧的相邻的节点</strong>都要注意,会跟之前的直接翻转链表有点区别,cur节点在后面就相当于已经翻转好的节点的集合,具体指向的是最后一个节点。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> ListNode <span class="hljs-title function_">reverseKGroup</span><span class="hljs-params">(ListNode head, <span class="hljs-type">int</span> k)</span> {<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">dummy</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">ListNode</span>(-<span class="hljs-number">1</span>, head), prev = dummy;<br> <span class="hljs-keyword">while</span>(<span class="hljs-literal">true</span>){<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">last</span> <span class="hljs-operator">=</span> prev;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i < k; i++){<br> last = last.next;<br> <span class="hljs-keyword">if</span>(last == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> dummy.next;<br> }<br> <span class="hljs-type">ListNode</span> <span class="hljs-variable">cur</span> <span class="hljs-operator">=</span> prev.next, next;<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i < k - <span class="hljs-number">1</span>; i++){<br> next = cur.next;<br> cur.next = next.next;<br> next.next = prev.next;<br> prev.next = next;<br> }<br> prev = cur;<br> }<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结: 翻转部分的链表与直接翻转整个链表还是有一些区别的,但是写起来起承转合的很优美哇~</li></ul>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>链表</tag>
</tags>
</entry>
<entry>
<title>黑马点评-短信登录</title>
<link href="/2024/02/01/%E7%BD%91%E4%B8%8A%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/%E7%9F%AD%E4%BF%A1%E7%99%BB%E5%BD%95/"/>
<url>/2024/02/01/%E7%BD%91%E4%B8%8A%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/%E7%9F%AD%E4%BF%A1%E7%99%BB%E5%BD%95/</url>
<content type="html"><![CDATA[<h2 id="基于Redis实现短信登录"><a href="#基于Redis实现短信登录" class="headerlink" title="基于Redis实现短信登录"></a>基于Redis实现短信登录</h2><h3 id="0-前言:"><a href="#0-前言:" class="headerlink" title="0.前言:"></a>0.前言:</h3><h4 id="短信验证登录过程中需要共享session:"><a href="#短信验证登录过程中需要共享session:" class="headerlink" title="短信验证登录过程中需要共享session:"></a>短信验证登录过程中需要<strong>共享session</strong>:</h4><ul><li>1.发送短信验证码:<strong>保存验证码到session</strong></li><li>2.短信验证码登录注册:根据手机号查询用户,如果是新用户要先进行注册,再<strong>保存用户到session</strong></li><li>3.验证登录状态:cookie中有<strong>sessionID</strong>,判断用户是否存在,进行拦截或者保存到ThreadLocal,再放行</li></ul><h4 id="问题:"><a href="#问题:" class="headerlink" title="问题:"></a>问题:</h4><ul><li>每个tomcat中都有一份属于自己的session,多台Tomcat不共享session存储空间,切换时数据丢失</li></ul><h4 id="替代要求:"><a href="#替代要求:" class="headerlink" title="替代要求:"></a>替代要求:</h4><ul><li>数据共享</li><li>内存存储,数据处理速度快</li><li>key,value结构</li></ul><p><strong>故选择Redis进行解决</strong></p><h3 id="1-采用Redis的业务流程:"><a href="#1-采用Redis的业务流程:" class="headerlink" title="1.采用Redis的业务流程:"></a>1.采用Redis的业务流程:</h3><img src="10.png" alt="发送验证码和登陆注册" width="800px"><img src="11.png" alt="登陆注册和校验登陆状态" width="800px"><h4 id="细节:"><a href="#细节:" class="headerlink" title="细节:"></a>细节:</h4><h5 id="1-key和数据结构的选择:"><a href="#1-key和数据结构的选择:" class="headerlink" title="1.key和数据结构的选择:"></a>1.key和数据结构的选择:</h5><ul><li>保存验证码:用手机号作为key<ul><li>手机号是唯一的,并且恰好与验证码绑定</li><li>采用String类型存储code</li></ul></li><li>保存用户对象:用随机生成的token作为key<ul><li>token需要传递给前端,并在每次请求中被携带,用手机号会有泄露风险</li><li>采用Hash结构存储用户对象,相比String采取Json格式,Hash结构每个字段相互独立,可以单独CRUD,并且内存占用更少</li></ul></li></ul><h5 id="2-选择合适的有效期:"><a href="#2-选择合适的有效期:" class="headerlink" title="2.选择合适的有效期:"></a>2.选择合适的有效期:</h5><ul><li>token要设置一定的有效期,用户长期不操作,就失去登录状态</li></ul><h5 id="3-选择合适的存储粒度DTO"><a href="#3-选择合适的存储粒度DTO" class="headerlink" title="3.选择合适的存储粒度DTO"></a>3.选择合适的存储粒度DTO</h5><ul><li>用户对象本身的信息是很丰富的,还包括手机号,密码等隐私信息,在登陆阶段不需要保存和传递这么多信息,可以新建一个UserDTO类来代替</li></ul><h3 id="2-技术要点:"><a href="#2-技术要点:" class="headerlink" title="2.技术要点:"></a>2.技术要点:</h3><h4 id="ThreadLocal"><a href="#ThreadLocal" class="headerlink" title="ThreadLocal:"></a>ThreadLocal:</h4><ul><li>在threadLocal中,他的put方法和他的get方法, 都是先从获得当前用户的线程,然后从线程中取出线程的成员变量map,只要线程不一样,map就不一样,所以可以通过这种方式来做到<strong>线程隔离</strong></li><li>所以可以实现每个用户的保存和相关信息的读取</li></ul><h4 id="User转Hash存储:"><a href="#User转Hash存储:" class="headerlink" title="User转Hash存储:"></a>User转Hash存储:</h4><ul><li>userDTO转Map再存储到Redis过程中,由于使用的是StringRedisTemplate要求所有的字段都是String类型,但是id是Long类型的,所以需要再进行一步手动转化</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><code class="hljs java">Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><>(),<br> CopyOptions.create()<br> .setIgnoreNullValue(<span class="hljs-literal">true</span>)<br> .setFieldValueEditor((fieldName, fieldValue) -> fieldValue.toString()));<br></code></pre></td></tr></table></figure><h4 id="刷新token有效期优化:"><a href="#刷新token有效期优化:" class="headerlink" title="刷新token有效期优化:"></a>刷新token有效期优化:</h4><p>在只有一个拦截器的情况下,拦截器里的过程:</p><ul><li>获取token信息</li><li>查询Redis的用户,不存在就拦截,存在就继续</li><li>保存到ThreadLocal中</li><li>刷新token有效期</li><li>放行</li></ul><p>那么如果用户进行了不需要登录验证的操作,比如查看首页,那么拦截器不会拦截,token就得不到刷新,是有问题的。</p><p><strong>解决:增加一个拦截一切路径的拦截器</strong></p><p>第一个拦截器:(所有路径)</p><ul><li>获取token信息</li><li>查询Redis的用户</li><li>保存到ThreadLocal中</li><li>刷新token有效期</li><li>放行</li></ul><p>第二个拦截器:(需要登陆的路径)</p><ul><li>不存在就拦截,存在就继续</li></ul><p>完美实现token的及时刷新</p>]]></content>
<categories>
<category>黑马点评</category>
</categories>
<tags>
<tag>短信登陆</tag>
</tags>
</entry>
<entry>
<title>Redis课程思维导图总结</title>
<link href="/2024/02/01/%E7%BD%91%E4%B8%8A%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/Redis%E8%AF%BE%E7%A8%8B/"/>
<url>/2024/02/01/%E7%BD%91%E4%B8%8A%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/Redis%E8%AF%BE%E7%A8%8B/</url>
<content type="html"><![CDATA[<h3 id="Redis基础篇"><a href="#Redis基础篇" class="headerlink" title="Redis基础篇"></a>Redis基础篇</h3><img src="01.png" alt="基础篇知识总结" width="1500px">]]></content>
<categories>
<category>黑马点评</category>
</categories>
<tags>
<tag>Redis</tag>
</tags>
</entry>
<entry>
<title>工程师的自我迭代-RedTech</title>
<link href="/2024/01/23/%E7%94%9F%E6%B4%BB%E4%B8%8E%E6%8A%80%E6%9C%AF/RedTech/"/>
<url>/2024/01/23/%E7%94%9F%E6%B4%BB%E4%B8%8E%E6%8A%80%E6%9C%AF/RedTech/</url>
<content type="html"><![CDATA[<h3 id="前言:"><a href="#前言:" class="headerlink" title="前言:"></a>前言:</h3><p>这篇文章是看了小红书有关“工程师自我迭代”的技术分享的一个总结复盘,It’s quite mind-opening。所以拖了好几天还是想小小总结反思一下,方便以后回看。</p><hr><h3 id="0-两种成功:合作成功和赋能成功"><a href="#0-两种成功:合作成功和赋能成功" class="headerlink" title="0.两种成功:合作成功和赋能成功"></a>0.两种成功:合作成功和赋能成功</h3><ul><li>说明:<ul><li>在职场上的工程师大概可以分为两阶段,一个是<strong>技术类工程师</strong>,一个是<strong>管理层工程师</strong>。这两个分别对应着两种不同的成功,即<strong>合作成功</strong>与<strong>赋能成功</strong>。</li></ul></li></ul><h3 id="1-合作成功:小T字型人才"><a href="#1-合作成功:小T字型人才" class="headerlink" title="1.合作成功:小T字型人才"></a>1.合作成功:小T字型人才</h3><ul><li>T的意思是分别对应”一“的深和”|“的广,深广须兼顾</li></ul><h4 id="1-1深度(自己的技术栈):"><a href="#1-1深度(自己的技术栈):" class="headerlink" title="1.1深度(自己的技术栈):"></a>1.1深度(自己的技术栈):</h4><p>说明:即对于自己的方向要足够深入,方方面面都了解</p><ul><li><strong>系统性</strong>——><em><u>我该如何搭建我的知识系统呢?</u></em></li><li><strong>深刻理解</strong>——><strong>有项目经历,有成果</strong></li></ul><p><em><u>系统性的搭建一方面可以基于学校的专业课程,一方面也要自己去探索</u></em></p><h4 id="1-2广度(相关的技术和业务):"><a href="#1-2广度(相关的技术和业务):" class="headerlink" title="1.2广度(相关的技术和业务):"></a>1.2广度(相关的技术和业务):</h4><p>说明:不能只专于自己的方向,对于相关的领域也要有所了解。比如演讲人是音视频方向的专家,那么他对于云原生,数据库,电商行业,直播互动也要有所涉足。</p><ul><li><strong>关键概念</strong></li><li><strong>语言体系</strong></li><li><strong>交互界面</strong></li></ul><p><em><u>以上三点总结来说就是<strong>知彼解己</strong>,即知道相关领域的人所说的关键概念,也能让对方知道自己在表达什么,形成一个良好的交互界面。</u></em></p><h3 id="2-赋能成功:大T字型人才"><a href="#2-赋能成功:大T字型人才" class="headerlink" title="2.赋能成功:大T字型人才"></a>2.赋能成功:大T字型人才</h3><ul><li>赋能成功,更多是指为他人赋能,为团队赋能</li></ul><h4 id="1-1深度:"><a href="#1-1深度:" class="headerlink" title="1.1深度:"></a>1.1深度:</h4><ul><li>技术的一个泛化,相当于小T字型人才的一个总和。此时会需要接触其他团队,比如说产品、运营,对于他们来说,技术是一个黑盒子的概念。</li></ul><h4 id="1-2广度:"><a href="#1-2广度:" class="headerlink" title="1.2广度:"></a>1.2广度:</h4><ul><li><p>术:表达、写作、逻辑 ===>说和写总归要擅长一个</p></li><li><p>道:理性、<strong>逻辑</strong>、修养、<strong>企图心</strong>、自我控制力</p><ul><li>怎么修?<ul><li><strong>主动积极</strong>(问题驱动,关注结果),达到<strong>以终为始</strong></li></ul></li></ul></li><li><p>信念:自我改变即迭代——><strong>不断更新</strong></p><ul><li><p>心态年轻:拥抱新事物</p></li><li><p>心智成熟:不做巨婴</p></li><li><p>巨婴:</p><ul><li>自我——>知彼解己,双赢思维,统合综效</li><li>只看眼前——>要事第一,以终为始</li><li>依赖性强——>主动积极</li><li>不再成长——>不断更新</li></ul></li></ul></li></ul><h3 id="3-管理者的“三会一懂”"><a href="#3-管理者的“三会一懂”" class="headerlink" title="3.管理者的“三会一懂”"></a>3.管理者的“三会一懂”</h3><ul><li>会定目标:<ul><li>五要素:具体、可衡量、可接受、结果导向、时限</li></ul></li><li>会开会<ul><li>例会、主题会,就不展开了</li></ul></li><li>会复盘<ul><li>小事及时复盘</li><li>大事阶段复盘</li><li>完事全面复盘</li></ul></li><li>懂战略<ul><li>战略即取舍</li><li><strong><u>战略不是关于未来做什么,而是“现在做什么的未来性”</u></strong> (整个分享我最爱的一句话!)</li></ul></li></ul><p>总结:</p><ul><li>虽然说是管理者的三会一懂,但我觉得很多道理是相通的,比如说制定目标的标准,还有我之前的复盘也多少受此影响,以及最后的战略,常思常新。</li></ul><h3 id="4-WWH视角"><a href="#4-WWH视角" class="headerlink" title="4.WWH视角"></a>4.WWH视角</h3><img src="11.png" alt="WWH" width="650px"><ul><li>WHY:<ul><li>为什么要做?</li><li>不做行不行?</li><li>以后再做行不行?</li></ul></li><li>WHAT:<ul><li>技术特点或关键点?</li><li>类似的技术,区别?</li><li>优缺点?成熟度?</li><li>收益与代价?</li></ul></li><li>HOW:<ul><li>如何避坑?</li><li>如何实验?</li><li>如何迭代?</li><li>如何工程化?</li></ul></li><li>总结:一个工程师的成长就是从只关注HOW上提升到逐渐涉及WHAT和WHY上的深入。当然,我觉得思考很多事情都可以尝试去套用这个,逻辑会很清晰。</li></ul><h3 id="5-总结与思考"><a href="#5-总结与思考" class="headerlink" title="5.总结与思考"></a>5.总结与思考</h3><ul><li>这里面提到了不少《高效能人士的七个习惯》的概念,给我一种世界尽头是这本书的感觉,之前没看进去。但结合实际来讲,其中的许多概念确实很先进,值得学习。</li><li>我的收获<ul><li>对于工程师的职业发展有了一个更大的视角,之前可能就是集中于技术的提升,现在发现很多软实力也非常值得关注,或者说是一种通用能力</li><li>如何制定规划,设定目标,底层来说要<strong>要事第一、以终为始</strong>,上层来说可以以五要素为基准拓展,打算拿这套来规划一下寒假,(但还没开始呢)</li><li>注重复盘的作用,及时复盘是个不错的习惯,一是理清思路,二是发挥事物的最大价值</li><li><strong>战略不是关于未来做什么,而是“现在做什么的未来性”</strong>,一句顶一万句的感觉</li><li>关于技术的系统性搭建,目前没什么思路,需要更多的学习吧,到一定程度俯览整个知识结构</li></ul></li></ul>]]></content>
<categories>
<category>人文</category>
</categories>
<tags>
<tag>自我成长</tag>
</tags>
</entry>
<entry>
<title>SQL的JOIN连接多表查询</title>
<link href="/2024/01/22/%E7%BD%91%E4%B8%8A%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/SQL%E7%9A%84JOIN%E8%BF%9E%E6%8E%A5%E5%A4%9A%E8%A1%A8%E6%9F%A5%E8%AF%A2/"/>
<url>/2024/01/22/%E7%BD%91%E4%B8%8A%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/SQL%E7%9A%84JOIN%E8%BF%9E%E6%8E%A5%E5%A4%9A%E8%A1%A8%E6%9F%A5%E8%AF%A2/</url>
<content type="html"><![CDATA[<h3 id="前言"><a href="#前言" class="headerlink" title="前言:"></a>前言:</h3><p>数据库上课时这一部分没有听进去,前几天面试又问到了SQL,现在才发现答得简直是乱七八糟,那就趁现在好好整理一下吧,感谢面试官的包容,I really appreciate that!</p><hr><h3 id="0-所有的JOINS概览"><a href="#0-所有的JOINS概览" class="headerlink" title="0.所有的JOINS概览"></a>0.所有的JOINS概览</h3><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span><br><span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span><br><span class="hljs-keyword">RIGHT</span> <span class="hljs-keyword">JOIN</span><br><span class="hljs-keyword">OUTER</span> <span class="hljs-keyword">JOIN</span><br><span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span> EXCLUDING <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span><br><span class="hljs-keyword">RIGHT</span> <span class="hljs-keyword">JOIN</span> EXCLUDING <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span><br><span class="hljs-keyword">OUTER</span> <span class="hljs-keyword">JOIN</span> EXCLUDING <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span><br><span class="hljs-keyword">CROSS</span> <span class="hljs-keyword">JOIN</span><br></code></pre></td></tr></table></figure><figure class="highlight brainfuck"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><code class="hljs brainfuck"><span class="hljs-comment">用于查询的两张表信息</span><br><span class="hljs-comment">TABLE_A</span><br> <span class="hljs-comment">PK Value</span><br><span class="hljs-literal">----</span> <span class="hljs-literal">----------</span><br> <span class="hljs-comment">1 FOX</span><br> <span class="hljs-comment">2 COP</span><br> <span class="hljs-comment">3 TAXI</span><br> <span class="hljs-comment">6 WASHINGTON</span><br> <span class="hljs-comment">7 DELL</span><br> <span class="hljs-comment">5 ARIZONA</span><br> <span class="hljs-comment">4 LINCOLN</span><br> <span class="hljs-comment">10 LUCENT</span><br><br><span class="hljs-comment">TABLE_B</span><br> <span class="hljs-comment">PK Value</span><br><span class="hljs-literal">----</span> <span class="hljs-literal">----------</span><br> <span class="hljs-comment">1 TROT</span><br> <span class="hljs-comment">2 CAR</span><br> <span class="hljs-comment">3 CAB</span><br> <span class="hljs-comment">6 MONUMENT</span><br> <span class="hljs-comment">7 PC</span><br> <span class="hljs-comment">8 MICROSOFT</span><br> <span class="hljs-comment">9 APPLE</span><br> <span class="hljs-comment">11 SCOTCH</span><br></code></pre></td></tr></table></figure><h3 id="1-Inner-JOIN内连接"><a href="#1-Inner-JOIN内连接" class="headerlink" title="1.Inner JOIN内连接"></a>1.Inner JOIN内连接</h3><img src="10.png" alt="内连接" width="300px"><p>说明:相当于取两张表的交集,JOIN没有特别说明时默认就是内连接</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> A.PK <span class="hljs-keyword">AS</span> A_PK, A.Value <span class="hljs-keyword">AS</span> A_Value,<br> B.Value <span class="hljs-keyword">AS</span> B_Value, B.PK <span class="hljs-keyword">AS</span> B_PK<br><span class="hljs-keyword">FROM</span> Table_A A<br><span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Table_B B<br><span class="hljs-keyword">ON</span> A.PK <span class="hljs-operator">=</span> B.PK<br></code></pre></td></tr></table></figure><p>结果:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><code class="hljs sql">A_PK A_Value B_Value B_PK<br><span class="hljs-comment">---- ---------- ---------- ----</span><br> <span class="hljs-number">1</span> FOX TROT <span class="hljs-number">1</span><br> <span class="hljs-number">2</span> COP CAR <span class="hljs-number">2</span><br> <span class="hljs-number">3</span> TAXI CAB <span class="hljs-number">3</span><br> <span class="hljs-number">6</span> WASHINGTON MONUMENT <span class="hljs-number">6</span><br> <span class="hljs-number">7</span> DELL PC <span class="hljs-number">7</span><br><br>(<span class="hljs-number">5</span> <span class="hljs-type">row</span>(s) affected)<br></code></pre></td></tr></table></figure><h3 id="2-Left-JOIN左连接"><a href="#2-Left-JOIN左连接" class="headerlink" title="2.Left JOIN左连接"></a>2.Left JOIN左连接</h3><img src="11.png" alt="左连接" width="300px"><p>说明:相当于取两张表的交集加上左表,即所有的左表数据都会被显示出来,不管有没有匹配的右表,没有的话右表部分就显示NULL</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> A.PK <span class="hljs-keyword">AS</span> A_PK, A.Value <span class="hljs-keyword">AS</span> A_Value,<br>B.Value <span class="hljs-keyword">AS</span> B_Value, B.PK <span class="hljs-keyword">AS</span> B_PK<br><span class="hljs-keyword">FROM</span> Table_A A<br><span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span> Table_B B<br><span class="hljs-keyword">ON</span> A.PK <span class="hljs-operator">=</span> B.PK<br></code></pre></td></tr></table></figure><p>结果:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs sql">A_PK A_Value B_Value B_PK<br><span class="hljs-comment">---- ---------- ---------- ----</span><br> <span class="hljs-number">1</span> FOX TROT <span class="hljs-number">1</span><br> <span class="hljs-number">2</span> COP CAR <span class="hljs-number">2</span><br> <span class="hljs-number">3</span> TAXI CAB <span class="hljs-number">3</span><br> <span class="hljs-number">4</span> LINCOLN <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br> <span class="hljs-number">5</span> ARIZONA <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br> <span class="hljs-number">6</span> WASHINGTON MONUMENT <span class="hljs-number">6</span><br> <span class="hljs-number">7</span> DELL PC <span class="hljs-number">7</span><br> <span class="hljs-number">10</span> LUCENT <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br></code></pre></td></tr></table></figure><h3 id="3-Right-JOIN右连接"><a href="#3-Right-JOIN右连接" class="headerlink" title="3.Right JOIN右连接"></a>3.Right JOIN右连接</h3><img src="12.png" alt="右连接" width="300px"><p>说明:相当于取两张表的交集加上右表,即所有的右表数据都会被显示出来,不管有没有匹配的左表,没有的话左表的部分就显示NULL</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> A.PK <span class="hljs-keyword">AS</span> A_PK, A.Value <span class="hljs-keyword">AS</span> A_Value,<br>B.Value <span class="hljs-keyword">AS</span> B_Value, B.PK <span class="hljs-keyword">AS</span> B_PK<br><span class="hljs-keyword">FROM</span> Table_A A<br><span class="hljs-keyword">RIGHT</span> <span class="hljs-keyword">JOIN</span> Table_B B<br><span class="hljs-keyword">ON</span> A.PK <span class="hljs-operator">=</span> B.PK<br></code></pre></td></tr></table></figure><p>结果:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs sql">A_PK A_Value B_Value B_PK<br><span class="hljs-comment">---- ---------- ---------- ----</span><br> <span class="hljs-number">1</span> FOX TROT <span class="hljs-number">1</span><br> <span class="hljs-number">2</span> COP CAR <span class="hljs-number">2</span><br> <span class="hljs-number">3</span> TAXI CAB <span class="hljs-number">3</span><br> <span class="hljs-number">6</span> WASHINGTON MONUMENT <span class="hljs-number">6</span><br> <span class="hljs-number">7</span> DELL PC <span class="hljs-number">7</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> MICROSOFT <span class="hljs-number">8</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> APPLE <span class="hljs-number">9</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> SCOTCH <span class="hljs-number">11</span><br><br>(<span class="hljs-number">8</span> <span class="hljs-type">row</span>(s) affected)<br><br></code></pre></td></tr></table></figure><h3 id="4-OUTER-JOIN外连接"><a href="#4-OUTER-JOIN外连接" class="headerlink" title="4.OUTER JOIN外连接"></a>4.OUTER JOIN外连接</h3><img src="13.png" alt="外连接" width="300px"><p>说明:会返回两张表的所有的记录,相当于两张表的并集</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> A.PK <span class="hljs-keyword">AS</span> A_PK, A.Value <span class="hljs-keyword">AS</span> A_Value,<br>B.Value <span class="hljs-keyword">AS</span> B_Value, B.PK <span class="hljs-keyword">AS</span> B_PK<br><span class="hljs-keyword">FROM</span> Table_A A<br><span class="hljs-keyword">FULL</span> <span class="hljs-keyword">OUTER</span> <span class="hljs-keyword">JOIN</span> Table_B B<br><span class="hljs-keyword">ON</span> A.PK <span class="hljs-operator">=</span> B.PK<br></code></pre></td></tr></table></figure><p>结果:sql server 里先显示内连接,再是右连接,最后是左连接</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs sql">A_PK A_Value B_Value B_PK<br><span class="hljs-comment">---- ---------- ---------- ----</span><br> <span class="hljs-number">1</span> FOX TROT <span class="hljs-number">1</span><br> <span class="hljs-number">2</span> COP CAR <span class="hljs-number">2</span><br> <span class="hljs-number">3</span> TAXI CAB <span class="hljs-number">3</span><br> <span class="hljs-number">6</span> WASHINGTON MONUMENT <span class="hljs-number">6</span><br> <span class="hljs-number">7</span> DELL PC <span class="hljs-number">7</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> MICROSOFT <span class="hljs-number">8</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> APPLE <span class="hljs-number">9</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> SCOTCH <span class="hljs-number">11</span><br> <span class="hljs-number">5</span> ARIZONA <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br> <span class="hljs-number">4</span> LINCOLN <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br> <span class="hljs-number">10</span> LUCENT <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br><br>(<span class="hljs-number">11</span> <span class="hljs-type">row</span>(s) affected)<br><br></code></pre></td></tr></table></figure><h3 id="5-Left-Excluding-JOIN左表唯一连接"><a href="#5-Left-Excluding-JOIN左表唯一连接" class="headerlink" title="5.Left Excluding JOIN左表唯一连接"></a>5.Left Excluding JOIN左表唯一连接</h3><img src="14.png" alt="左表唯一连接" width="300px"><p>说明:会返回左表中与右表不能匹配的所有记录</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> A.PK <span class="hljs-keyword">AS</span> A_PK, A.Value <span class="hljs-keyword">AS</span> A_Value,<br>B.Value <span class="hljs-keyword">AS</span> B_Value, B.PK <span class="hljs-keyword">AS</span> B_PK<br><span class="hljs-keyword">FROM</span> Table_A A<br><span class="hljs-keyword">LEFT</span> <span class="hljs-keyword">JOIN</span> Table_B B<br><span class="hljs-keyword">ON</span> A.PK <span class="hljs-operator">=</span> B.PK<br><span class="hljs-keyword">WHERE</span> B.PK <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span><br></code></pre></td></tr></table></figure><p>结果:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs sql">A_PK A_Value B_Value B_PK<br><span class="hljs-comment">---- ---------- ---------- ----</span><br> <span class="hljs-number">4</span> LINCOLN <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br> <span class="hljs-number">5</span> ARIZONA <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br> <span class="hljs-number">10</span> LUCENT <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br>(<span class="hljs-number">3</span> <span class="hljs-type">row</span>(s) affected)<br><br></code></pre></td></tr></table></figure><h3 id="6-Right-Excluding-JOIN右表唯一连接"><a href="#6-Right-Excluding-JOIN右表唯一连接" class="headerlink" title="6.Right Excluding JOIN右表唯一连接"></a>6.Right Excluding JOIN右表唯一连接</h3><img src="15.png" alt="右表唯一连接" width="300px"><p>说明:会返回右表中与左表不能匹配的所有记录</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> A.PK <span class="hljs-keyword">AS</span> A_PK, A.Value <span class="hljs-keyword">AS</span> A_Value,<br>B.Value <span class="hljs-keyword">AS</span> B_Value, B.PK <span class="hljs-keyword">AS</span> B_PK<br><span class="hljs-keyword">FROM</span> Table_A A<br><span class="hljs-keyword">RIGHT</span> <span class="hljs-keyword">JOIN</span> Table_B B<br><span class="hljs-keyword">ON</span> A.PK <span class="hljs-operator">=</span> B.PK<br><span class="hljs-keyword">WHERE</span> A.PK <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span><br></code></pre></td></tr></table></figure><p>结果:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs sql">A_PK A_Value B_Value B_PK<br><span class="hljs-comment">---- ---------- ---------- ----</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> MICROSOFT <span class="hljs-number">8</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> APPLE <span class="hljs-number">9</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> SCOTCH <span class="hljs-number">11</span><br><br>(<span class="hljs-number">3</span> <span class="hljs-type">row</span>(s) affected)<br><br></code></pre></td></tr></table></figure><h3 id="7-Outer-Excluding-JOIN非交集连接"><a href="#7-Outer-Excluding-JOIN非交集连接" class="headerlink" title="7.Outer Excluding JOIN非交集连接"></a>7.Outer Excluding JOIN非交集连接</h3><img src="16.png" alt="非交集连接" width="300px"><p>说明:会返回左表和右表里没有相互关联的记录</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> A.PK <span class="hljs-keyword">AS</span> A_PK, A.Value <span class="hljs-keyword">AS</span> A_Value,<br>B.Value <span class="hljs-keyword">AS</span> B_Value, B.PK <span class="hljs-keyword">AS</span> B_PK<br><span class="hljs-keyword">FROM</span> Table_A A<br><span class="hljs-keyword">FULL</span> <span class="hljs-keyword">OUTER</span> <span class="hljs-keyword">JOIN</span> Table_B B<br><span class="hljs-keyword">ON</span> A.PK <span class="hljs-operator">=</span> B.PK<br><span class="hljs-keyword">WHERE</span> A.PK <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span><br><span class="hljs-keyword">OR</span> B.PK <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span><br></code></pre></td></tr></table></figure><p>结果:</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs sql">A_PK A_Value B_Value B_PK<br><span class="hljs-comment">---- ---------- ---------- ----</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> MICROSOFT <span class="hljs-number">8</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> APPLE <span class="hljs-number">9</span><br><span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span> SCOTCH <span class="hljs-number">11</span><br> <span class="hljs-number">5</span> ARIZONA <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br> <span class="hljs-number">4</span> LINCOLN <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br> <span class="hljs-number">10</span> LUCENT <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">NULL</span><br><br>(<span class="hljs-number">6</span> <span class="hljs-type">row</span>(s) affected)<br><br></code></pre></td></tr></table></figure><h3 id="8-Cross-JOIN交叉连接"><a href="#8-Cross-JOIN交叉连接" class="headerlink" title="8.Cross JOIN交叉连接"></a>8.Cross JOIN交叉连接</h3><img src="17.png" alt="交叉连接" width="300px"><p>说明:一张表中的数据依次取出分别与另一张表中的每条数据挨个组合,最后记录数量为两张表记录数的乘积,就是笛卡尔积。</p><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql">例如:<span class="hljs-keyword">SELECT</span> <span class="hljs-operator">*</span> <span class="hljs-keyword">FROM</span> student <span class="hljs-keyword">CROSS</span> <span class="hljs-keyword">JOIN</span> major<br></code></pre></td></tr></table></figure><h3 id="9-有关Where的多表连接查询"><a href="#9-有关Where的多表连接查询" class="headerlink" title="9.有关Where的多表连接查询"></a>9.有关Where的多表连接查询</h3><h4 id="9-1where和inner-join的区别:"><a href="#9-1where和inner-join的区别:" class="headerlink" title="9.1where和inner join的区别:"></a>9.1where和inner join的区别:</h4><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> a.ID, b.Name, b.Date <span class="hljs-keyword">FROM</span> Customers a, Sales b <span class="hljs-keyword">WHERE</span> a.ID <span class="hljs-operator">=</span> b.ID;<br></code></pre></td></tr></table></figure><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><code class="hljs sql"><span class="hljs-keyword">SELECT</span> a.ID, b.Name, b.Date <span class="hljs-keyword">FROM</span> Customers a <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Sales b <span class="hljs-keyword">ON</span> a.ID <span class="hljs-operator">=</span> b.ID;<br></code></pre></td></tr></table></figure><p>两者的结果是一样的。</p><p>但是<strong>where</strong>是实际上是创建了两张表的<strong>笛卡尔积</strong>,然后再做筛选过滤。如果两张表各有1000条记录,就会先产生1000000个结果,然后通过正确的 ID过滤出符合1000条记录。</p><p>而使用<strong>inner join</strong> 这样数据库就只产生符合的1000条目标结果,相比之下,查询效率更高。</p><h4 id="9-2on和where的区别:"><a href="#9-2on和where的区别:" class="headerlink" title="9.2on和where的区别:"></a>9.2on和where的区别:</h4><ul><li>对于left join:</li><li>on条件是<strong>生成临时表时的条件</strong>,无论on的条件是否为真,左表的数据都会返回,只是右表数据这是都会变成null,这是Left Join的特性(Right Join同)</li><li>where是在<strong>临时表创建完后</strong>根据条件进行筛选</li><li>即:<strong>先on 建立临时表再where进行筛选</strong></li></ul><h3 id="最后的全家福"><a href="#最后的全家福" class="headerlink" title="最后的全家福"></a>最后的全家福</h3><img src="20.png" alt="所有连接" width="300px"><hr><h3 id=""><a href="#" class="headerlink" title=""></a></h3><p>参考文章1:<a href="https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins">https://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins</a></p><p>参考文章2:<a href="https://zhuanlan.zhihu.com/p/68136613">https://zhuanlan.zhihu.com/p/68136613</a></p>]]></content>
<categories>
<category>数据库</category>
</categories>
<tags>
<tag>SQL</tag>
</tags>
</entry>
<entry>
<title>SpringBoot-demo-HelloWorld</title>
<link href="/2024/01/21/%E7%BD%91%E4%B8%8A%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/SpringBoot-demo-HelloWorld/"/>
<url>/2024/01/21/%E7%BD%91%E4%B8%8A%E6%8A%80%E6%9C%AF%E5%AD%A6%E4%B9%A0/SpringBoot-demo-HelloWorld/</url>
<content type="html"><![CDATA[<h1 id="spring-boot-demo-helloworld"><a href="#spring-boot-demo-helloworld" class="headerlink" title="spring-boot-demo-helloworld"></a>spring-boot-demo-helloworld</h1><h3 id="1-总体说明"><a href="#1-总体说明" class="headerlink" title="1.总体说明"></a>1.总体说明</h3><ul><li>一个基本的SpringBoot应用程序,其中包含一个Restful控制器,用于响应http的get请求。</li></ul><h3 id="2-代码"><a href="#2-代码" class="headerlink" title="2.代码"></a>2.代码</h3><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-meta">@SpringBootApplication</span><br><span class="hljs-meta">@RestController</span><br><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">SpringBootDemoHelloworldApplication</span> { <span class="hljs-comment">//主类</span><br><br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">main</span><span class="hljs-params">(String[] args)</span> { <span class="hljs-comment">//程序入口并启动SpringBoot应用程序</span><br> SpringApplication.run(SpringBootDemoHelloworldApplication.class, args);<br> } <br><br> <span class="hljs-comment">/**</span><br><span class="hljs-comment"> * Hello,World</span><br><span class="hljs-comment"> *</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@param</span> who 参数,非必须</span><br><span class="hljs-comment"> * <span class="hljs-doctag">@return</span> Hello, ${who}</span><br><span class="hljs-comment"> */</span><br> <span class="hljs-meta">@GetMapping("/hello")</span> <span class="hljs-comment">//使用HTTP的get请求,将“/hello”路径映射到sayHello方法</span><br> <span class="hljs-keyword">public</span> String <span class="hljs-title function_">sayHello</span><span class="hljs-params">(<span class="hljs-meta">@RequestParam(required = false, name = "who")</span> String who)</span> {<span class="hljs-comment">//接受一个可选的查询参数名为who,绑定到参数who上</span><br> <span class="hljs-keyword">if</span> (StrUtil.isBlank(who)) {<br> who = <span class="hljs-string">"World"</span>;<br> }<br> <span class="hljs-keyword">return</span> StrUtil.format(<span class="hljs-string">"Hello, {}!"</span>, who); <span class="hljs-comment">//将占位符{}用"who"参数的值替换</span><br> }<br>}<br></code></pre></td></tr></table></figure><h3 id="3-详细解释"><a href="#3-详细解释" class="headerlink" title="3.详细解释"></a>3.详细解释</h3><ul><li><strong>@SpringBootApplication</strong>:标记SpringBoot应用程序的<strong>主类</strong>,是一个<strong>配置类</strong>,并启用了Spring<u>上下文</u>的自动配置</li><li><strong>@RestController</strong>:定义Spring MVC应用程序中的<strong>控制器类</strong>,表示类中方法的返回值是**<u>HTTP响应体</u>**(而不是依赖于视图技术)。</li></ul><h3 id="4-一些深入"><a href="#4-一些深入" class="headerlink" title="4.一些深入"></a>4.一些深入</h3><h4 id="4-1-什么是Sping上下文?"><a href="#4-1-什么是Sping上下文?" class="headerlink" title="4.1 什么是Sping上下文?"></a>4.1 什么是Sping上下文?</h4><p><em>Spring 上下文(Spring Context)是 Spring 框架中的一个核心概念,它是一个<strong>对象容器</strong>,负责管理和维护应用程序中的所有<strong>对象(bean)</strong>。Spring 上下文充当了容器,负责<strong>加载、配置和组织</strong>应用程序中的各个组件,以及<strong>管理</strong>它们之间的<strong>依赖关系</strong>。</em></p><ul><li>我的理解:感觉还是有点抽象,先留个印象吧</li></ul><h4 id="4-2-什么是视图技术?"><a href="#4-2-什么是视图技术?" class="headerlink" title="4.2 什么是视图技术?"></a>4.2 什么是视图技术?</h4><p>常见的视图技术包括:</p><ol><li><strong>JSP(JavaServer Pages):</strong> JSP 是一种基于 Java 的服务器端模板技术,允许将 Java 代码嵌入到 HTML 页面中。JSP 文件通常包含 HTML 标记和嵌入的 Java 代码,用于动态生成页面内容。</li><li><strong>Thymeleaf:</strong> Thymeleaf 是一种现代的服务器端模板引擎,支持自然的模板语法,而且可以直接在浏览器中预览模板。它特别适用于构建 HTML5 页面。</li></ol><p><code>@Controller</code> 注解通常与视图技术结合使用,将处理结果封装到模型中,然后选择适当的<u>视图来呈现这些模型数据</u>。</p><p> <code>@RestController</code> 注解表示控制器类的方法的返回值<u><strong>直接作为 HTTP 响应体</strong></u>,不再依赖于视图技术。</p><h4 id="4-3遇到的问题和解决"><a href="#4-3遇到的问题和解决" class="headerlink" title="4.3遇到的问题和解决"></a>4.3遇到的问题和解决</h4><ul><li>问题:自己照着编写了一个MyHelloworldApplication,但是运行失败</li><li>原因分析:两个主类基本一致,产生了<strong>映射冲突</strong>,导致两个不同的 <code>@RestController</code> 类中的相同路径 <code>/hello</code> 被映射到了相同的方法上</li><li>解决:更改其中一个路径为/myHello,解决问题</li></ul>]]></content>
<categories>
<category>SpringBoot-Demo</category>
</categories>
<tags>
<tag>SpringBoot</tag>
</tags>
</entry>
<entry>
<title>力扣二叉树部分题目题解---基本完成啦~</title>
<link href="/2024/01/20/%E5%8A%9B%E6%89%A3%E7%AE%97%E6%B3%95%E9%A2%98/%E5%8A%9B%E6%89%A3%E4%BA%8C%E5%8F%89%E6%A0%91%E9%83%A8%E5%88%86%E9%A2%98%E7%9B%AE%E6%80%BB%E7%BB%93/"/>
<url>/2024/01/20/%E5%8A%9B%E6%89%A3%E7%AE%97%E6%B3%95%E9%A2%98/%E5%8A%9B%E6%89%A3%E4%BA%8C%E5%8F%89%E6%A0%91%E9%83%A8%E5%88%86%E9%A2%98%E7%9B%AE%E6%80%BB%E7%BB%93/</url>
<content type="html"><![CDATA[<h2 id="二叉树"><a href="#二叉树" class="headerlink" title="二叉树"></a>二叉树</h2><h3 id="前言:"><a href="#前言:" class="headerlink" title="前言:"></a>前言:</h3><p>对于树一直是有一种惧怕心理的,题目做的不够多,有思路都不知道怎么实现,希望通过这次二叉树的专项练习,可以入个门吧~~~:)</p><hr><h3 id="1-二叉树展开为链表"><a href="#1-二叉树展开为链表" class="headerlink" title="1.二叉树展开为链表"></a>1.二叉树展开为链表</h3><ul><li>描述:把一棵二叉树展开为一条链表,链表的顺序就是二叉树的先序遍历顺序,链表实际上就是特殊的二叉树</li><li>总体说明:<ul><li>在原先基础上建立链表<ul><li>迭代,划分为三大模块再处理里面的内容(解法一)</li><li>先序遍历的逆过程,递归(解法二)</li><li>栈保存左右子树信息(解法三)</li></ul></li><li>新建链表(先序遍历保存下来,再形成链表)(解法四)<ul><li>递归或者的迭代的方式进行先序遍历依次保存节点</li></ul></li></ul></li></ul><h4 id="解法一:"><a href="#解法一:" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li><p>思路:按照先序遍历的思路<strong>直接在二叉树上做修改(迭代)</strong>,先是根节点,然后是左子树,最后是右子树;迭代每个根节点,把右子树挂到左子树的最右子节点,然后把左子树移到右子树的位置,原先的左子树置空。</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs Java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">flatten</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">while</span>(root != <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">if</span>(root.left == <span class="hljs-literal">null</span>){<br> root = root.right;<br> }<span class="hljs-keyword">else</span>{<br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">tmp</span> <span class="hljs-operator">=</span> root.left;<br> <span class="hljs-keyword">while</span>(tmp.right != <span class="hljs-literal">null</span>){ <span class="hljs-comment">//遍历找到左子树的最右子节点</span><br> tmp = tmp.right;<br> }<br> tmp.right = root.right;<br> root.right = root.left;<br> root.left = <span class="hljs-literal">null</span>;<br> root = root.right;<br> }<br> }<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:根据先序遍历,<u>把根节点,左子树,右子树先作为三个part连成一个链表</u>,然后再依次<strong>迭代</strong>里面的内容</li></ul><h4 id="解法二"><a href="#解法二" class="headerlink" title="解法二"></a>解法二</h4><ul><li><p>思路:先序遍历的逆过程。如果从根节点开始按照先序遍历的顺序<strong>直接</strong>建立链表,那么它的右节点就会还没有遍历到就直接被覆盖掉了。所以转换思维,从链尾开始倒着建立链表(root.right=pre,root.left=null)pre是链表上当前root的后一个节点,根据先右子树后左子树的<strong>递归</strong>,<strong>自底向上</strong>倒序连接形成链表。</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> TreeNode pre;<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">flatten</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>;<br> flatten(root.right);<br> flatten(root.left);<br> root.right = pre;<br> root.left = <span class="hljs-literal">null</span>; <br> pre = root;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:很棒的想法,通过递归实现的顺序是<u><strong>右子树,左子树,根节点</strong></u>,刚好是先序遍历(根节点,左子树,右子树)的逆序,再逐步组织链表。</li></ul><h4 id="解法三:"><a href="#解法三:" class="headerlink" title="解法三:"></a>解法三:</h4><ul><li><p>思路:之前提到直接按照先序遍历建立链表会覆盖掉原先的右子树,那么可以通过<strong>栈的方式保存子树信息</strong>,先存右子树,再存左子树,申明一个前置节点,刚开始是root,从栈中先取出来的是左子树的根节点,pre.right = cur; pre.left = null;然后更新pre即可。最终实现<strong>自顶向下</strong>建立链表。</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">flatten</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>;<br> Deque<TreeNode> stack = <span class="hljs-keyword">new</span> <span class="hljs-title class_">LinkedList</span><>();<br> stack.push(root);<br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">pre</span> <span class="hljs-operator">=</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-keyword">while</span>(!stack.isEmpty()){<br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">cur</span> <span class="hljs-operator">=</span> stack.pop();<br> <span class="hljs-keyword">if</span>(pre != <span class="hljs-literal">null</span>){<br> pre.right = cur;<br> pre.left = <span class="hljs-literal">null</span>;<br> }<br> <span class="hljs-keyword">if</span>(cur.right != <span class="hljs-literal">null</span>){<br> stack.push(cur.right);<br> }<br> <span class="hljs-keyword">if</span>(cur.left != <span class="hljs-literal">null</span>){<br> stack.push(cur.left);<br> }<br> pre = cur;<br> }<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:递归迭代这些好像经常可以和栈联系起来,栈的作用主要是<strong>保存状态</strong>,使得程序的遍历可以更加符合**<u>顺序逻辑</u>**。</li></ul><h4 id="解法四:"><a href="#解法四:" class="headerlink" title="解法四:"></a>解法四:</h4><ul><li>思路:以上的方法都是直接在二叉树上修改,使之变成链表,实际上也可以直接申明一个List<Treenode> 类型的list,先序遍历二叉树,把节点按顺序放入list,最后连接起一个链表即可。</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs Java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">flatten</span><span class="hljs-params">(TreeNode root)</span> {<br> List<TreeNode> list = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><>();<br> preorderTraversal(root, list);<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i < list.size()-<span class="hljs-number">1</span>; i++){ <span class="hljs-comment">//List类型转为单向链表</span><br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">cur</span> <span class="hljs-operator">=</span> list.get(i), next = list.get(i + <span class="hljs-number">1</span>);<br> cur.right = next;<br> cur.left = <span class="hljs-literal">null</span>;<br> }<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">preorderTraversal</span><span class="hljs-params">(TreeNode root, List<TreeNode> list)</span>{<br> <span class="hljs-keyword">if</span>(root != <span class="hljs-literal">null</span>){<br> list.add(root);<br> preorderTraversal(root.left, list);<br> preorderTraversal(root.right, list);<br> }<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:对于这种简单的递归要尽可能地熟练,并不难。</li></ul><h3 id="2-将有序数组转换为二叉搜索树"><a href="#2-将有序数组转换为二叉搜索树" class="headerlink" title="2.将有序数组转换为二叉搜索树"></a>2.将有序数组转换为二叉搜索树</h3><ul><li>描述:给定一个升序数组,将其转化为一个高度平衡的二叉搜索树,即中序遍历是个升序数组</li></ul><h4 id="解法一:-1"><a href="#解法一:-1" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li><p>思路:高度平衡,考虑把中间位置作为根节点进行建树,再递归调用建立左右子树即可。</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">sortedArrayToBST</span><span class="hljs-params">(<span class="hljs-type">int</span>[] nums)</span> {<br> <span class="hljs-keyword">return</span> helper(nums, <span class="hljs-number">0</span>, nums.length - <span class="hljs-number">1</span>);<br> }<br> <span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">helper</span><span class="hljs-params">(<span class="hljs-type">int</span>[] nums, <span class="hljs-type">int</span> left, <span class="hljs-type">int</span> right)</span>{<br> <span class="hljs-keyword">if</span>(left > right) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">mid</span> <span class="hljs-operator">=</span> (left + right)/<span class="hljs-number">2</span>;<br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">root</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">TreeNode</span>(nums[mid]);<br> root.left = helper(nums, left, mid -<span class="hljs-number">1</span>);<br> root.right = helper(nums, mid + <span class="hljs-number">1</span>, right);<br> <span class="hljs-keyword">return</span> root;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:数组转化为二叉树思路并不难,只是对树的建立过程不够熟悉。因为涉及递归,最好新建一个函数。</li></ul><h3 id="3-二叉树的最近公共祖先"><a href="#3-二叉树的最近公共祖先" class="headerlink" title="3.二叉树的最近公共祖先"></a>3.二叉树的最近公共祖先</h3><ul><li>描述:给定一个二叉树, 找到该树中两个指定节点的最近公共祖先</li></ul><h4 id="解法一:-2"><a href="#解法一:-2" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li><p>思路:通过递归分别去左右子树寻找,一旦找到p或q,直接返回,或者两者分别在左右子树,返回当前的root</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs Java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">lowestCommonAncestor</span><span class="hljs-params">(TreeNode root, TreeNode p, TreeNode q)</span> {<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span> || root == p || root == q) <span class="hljs-keyword">return</span> root;<br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">left</span> <span class="hljs-operator">=</span> lowestCommonAncestor(root.left, p, q);<br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">right</span> <span class="hljs-operator">=</span> lowestCommonAncestor(root.right, p, q);<br> <span class="hljs-keyword">if</span>(left == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> right;<br> <span class="hljs-keyword">if</span>(right == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> left;<br> <span class="hljs-keyword">return</span> root;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:很精彩的递归,尤其是return root 这里,空的会向上传,直到有一个left和right都恰好是非空。</li></ul><h4 id="解法二:"><a href="#解法二:" class="headerlink" title="解法二:"></a>解法二:</h4><ul><li><p>思路:先提前dfs整棵树,确定所有的父节点,然后找出p的父节点这条路,再找q的所有祖先,一旦之前找到过,就是最近的公共祖先。<strong>另外,题目说明所有 <code>Node.val</code> <code>互不相同</code> ,故可以Map存储节点的值。</strong></p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> Map<Integer, TreeNode> parent = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><>();<br> Set<Integer> visited = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashSet</span><>();<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">dfs</span><span class="hljs-params">(TreeNode root)</span>{<br> <span class="hljs-keyword">if</span>(root.left != <span class="hljs-literal">null</span>){<br> parent.put(root.left.val, root);<br> dfs(root.left);<br> }<br> <span class="hljs-keyword">if</span>(root.right != <span class="hljs-literal">null</span>){<br> parent.put(root.right.val, root);<br> dfs(root.right);<br> }<br><br> }<br><span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">lowestCommonAncestor</span><span class="hljs-params">(TreeNode root, TreeNode p, TreeNode q)</span> {<br> dfs(root);<br> <span class="hljs-keyword">while</span>(p != <span class="hljs-literal">null</span>){<br> visited.add(p.val);<br> p = parent.get(p.val);<br> }<br> <span class="hljs-keyword">while</span>(q != <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">if</span>(visited.contains(q.val)){<br> <span class="hljs-keyword">return</span> q;<br> }<br> q = parent.get(q.val);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:这个代码相对递归更好理解,就是直观的解法,后面的p,q就不是这两个点了,而是它们所有直接祖先这条线上的点。</li></ul><h3 id="4-把二叉搜索树转化为累加树"><a href="#4-把二叉搜索树转化为累加树" class="headerlink" title="4.把二叉搜索树转化为累加树"></a>4.把二叉搜索树转化为累加树</h3><ul><li>描述:给定一个二叉搜索树,请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。补充:二叉搜索树的中序遍历是一个升序数组。</li></ul><h4 id="解法一:-3"><a href="#解法一:-3" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:逆向思维,从二叉搜索树的最右子节点开始,以中序遍历的逆过程(<strong>右子树,根节点,左子树</strong>)遍历,其值就是当前遍历过的节点的不断累加。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs Java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-type">int</span> <span class="hljs-variable">sum</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">convertBST</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> convertBST(root.right);<br> sum += root.val;<br> root.val = sum;<br> convertBST(root.left);<br> <span class="hljs-keyword">return</span> root;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:增加了递归的熟练度,宏观来看就是<strong>右子树,根节点,左子树</strong>的顺序,具体的实现细节也要验证符合要求,很锻炼思维能力。</li></ul><h3 id="5-路径总和"><a href="#5-路径总和" class="headerlink" title="5.路径总和|||"></a>5.路径总和|||</h3><ul><li>描述:给定一个二叉树的根节点 <code>root</code> ,和一个整数 <code>targetSum</code> ,求该二叉树里节点值之和等于 <code>targetSum</code> 的 路径 的数目。路径 不需要从根节点开始,也不需要在叶子节点结束,但是路径方向必须是向下的(只能从父节点到子节点)。</li></ul><h4 id="解法一:-4"><a href="#解法一:-4" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:路径是从父节点到根节点,那么可以深度搜索遍历整棵树,同时维护一个前缀和的哈希数组,键是当前节点之前出现过的前缀和,值出现的次数,cur代表从根节点到达当前节点的所有的和。</li><li>代码</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">pathSum</span><span class="hljs-params">(TreeNode root, <span class="hljs-type">int</span> targetSum)</span> {<br> Map<Long, Integer> prefix = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><>();<br> prefix.put(<span class="hljs-number">0L</span>, <span class="hljs-number">1</span>);<br> <span class="hljs-keyword">return</span> dfs(root, prefix, <span class="hljs-number">0</span>, targetSum);<br> }<br> <span class="hljs-keyword">public</span> Integer <span class="hljs-title function_">dfs</span><span class="hljs-params">(TreeNode root, Map<Long, Integer> prefix, <span class="hljs-type">long</span> cur, <span class="hljs-type">int</span> targetSum{</span><br><span class="hljs-params"> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>)</span> <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">ret</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; <span class="hljs-comment">//ret每次进来重新赋值,但由于下面的+=,最后会累加成最终的结果</span><br> cur += root.val;<br> ret = prefix.getOrDefault(cur - targetSum,<span class="hljs-number">0</span>);<br> prefix.put(cur, prefix.getOrDefault(cur, <span class="hljs-number">0</span>) + <span class="hljs-number">1</span>);<br> ret += dfs(root.left, prefix, cur, targetSum);<br> ret += dfs(root.right, prefix, cur, targetSum);<br> prefix.put(cur,prefix.getOrDefault(cur, <span class="hljs-number">0</span>) - <span class="hljs-number">1</span>); <span class="hljs-comment">//跳转到另一颗子树,必须恢复现场</span><br> <span class="hljs-keyword">return</span> ret;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:二叉树还是跟递归关系很大,主要是利用了前缀和的思想和Map这一键值对的数据结构,还有就是当当前节点遍历完,换到另一颗子树时一定要恢复现场,才能保证prefix的准确性。</li></ul><h3 id="6-二叉搜索树中第K小的元素"><a href="#6-二叉搜索树中第K小的元素" class="headerlink" title="6.二叉搜索树中第K小的元素"></a>6.二叉搜索树中第K小的元素</h3><ul><li>描述:给定一个二叉搜索树的根节点 <code>root</code> ,和一个整数 <code>k</code> ,请你设计一个算法查找其中第 <code>k</code> 个最小元素(从 1 开始计数)。</li></ul><h4 id="解法一:-5"><a href="#解法一:-5" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li><p>思路:二叉搜索树的特点是中序遍历是一个升序数组,那么直接进行中序遍历,保存到数组里,取第k个元素的值即可,是自己写出来的一道题呦~o(<em> ̄▽ ̄</em>)ブ</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">kthSmallest</span><span class="hljs-params">(TreeNode root, <span class="hljs-type">int</span> k)</span> {<br> List<TreeNode> list = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><>();<br> middleOrderTravesal(root,list);<br> <span class="hljs-keyword">return</span> list.get(k-<span class="hljs-number">1</span>).val;<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">middleOrderTravesal</span><span class="hljs-params">(TreeNode root, List<TreeNode> list)</span>{<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>;<br> middleOrderTravesal(root.left, list);<br> list.add(root);<br> middleOrderTravesal(root.right, list);<br> <span class="hljs-keyword">return</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:二叉树果然还是和递归或者遍历分不开,做多了就渐渐有感觉了。</li></ul><h3 id="7-二叉树的右视图"><a href="#7-二叉树的右视图" class="headerlink" title="7.二叉树的右视图"></a>7.二叉树的右视图</h3><ul><li>描述:给定一个二叉树的 <strong>根节点</strong> <code>root</code>,想象自己站在它的右侧,按照从顶部到底部的顺序,返回从右侧所能看到的节点值。</li></ul><h4 id="解法一:-6"><a href="#解法一:-6" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:先右子树后左子树地递归,维护一个深度变量,如果是第一次到达该层就添加进答案,这样就满足右视图的要求了。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-type">int</span> <span class="hljs-variable">dep</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>;<br> <span class="hljs-keyword">public</span> List<Integer> <span class="hljs-title function_">rightSideView</span><span class="hljs-params">(TreeNode root)</span> {<br> List<Integer> right_view = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><>();<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> right_view;<br> dfs(root, right_view, <span class="hljs-number">0</span>);<br> <span class="hljs-keyword">return</span> right_view;<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">dfs</span><span class="hljs-params">(TreeNode root, List<Integer> right_view, <span class="hljs-type">int</span> depth)</span>{<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>;<br> depth++;<br> <span class="hljs-keyword">if</span>(depth > dep){<br> right_view.add(root.val);<br> dep = depth;<br> }<br> dfs(root.right, right_view, depth);<br> dfs(root.left, right_view ,depth);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:刚开始没有想到有可能右子树不存在,看到的是左子树的节点。所以需要维护一个深度,这部分有点思路但不太会实现,实际上就是通过一个全局变量来找到该层出现的第一个节点。</li></ul><h3 id="8-二叉树中的最大路径和"><a href="#8-二叉树中的最大路径和" class="headerlink" title="8.二叉树中的最大路径和"></a>8.二叉树中的最大路径和</h3><ul><li>描述:二叉树中的 <strong>路径</strong> 被定义为一条节点序列,序列中每对相邻节点之间都存在一条边。同一个节点在一条路径序列中 <strong>至多出现一次</strong> 。该路径 <strong>至少包含一个</strong> 节点,且不一定经过根节点。<strong>路径和</strong> 是路径中各节点值的总和。给你一个二叉树的根节点 <code>root</code> ,返回其 <strong>最大路径和</strong> 。</li></ul><h4 id="解法一:-7"><a href="#解法一:-7" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:首先,这是个可递归的问题,对于每个节点,可以<strong>递归</strong>找到<strong>以它为根节点的且向下的路径和的最大值</strong>,那么对于整体的二叉树的最大路径和,可以在递归过程中,不断比较<strong>节点的值加上其左右子节点的最大路径和</strong>,最终找到最大路径和。由于存在负数,要和0比较一下。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-type">int</span> <span class="hljs-variable">maxSum</span> <span class="hljs-operator">=</span> Integer.MIN_VALUE;<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">maxPathSum</span><span class="hljs-params">(TreeNode root)</span> {<br> maxGain(root);<br> <span class="hljs-keyword">return</span> maxSum;<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">maxGain</span><span class="hljs-params">(TreeNode node)</span>{<br> <span class="hljs-keyword">if</span>(node == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">leftGain</span> <span class="hljs-operator">=</span> Math.max(<span class="hljs-number">0</span>, maxGain(node.left));<br> <span class="hljs-type">int</span> <span class="hljs-variable">rightGain</span> <span class="hljs-operator">=</span> Math.max(<span class="hljs-number">0</span>,maxGain(node.right));<br> maxSum = Math.max(maxSum, node.val + leftGain + rightGain); <span class="hljs-comment">//递归完后就可以把该节点作为候选节点</span><br> <span class="hljs-keyword">return</span> node.val + Math.max(leftGain, rightGain);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:感觉以前好像做过,但是对于递归的熟悉还是不够,相当于把最终的路径按最上面的节点进行拆分为三个部分(当前节点,左子树的一条最大路径,右子树的一条最大路径),那么问题就转变为递归每个节点的最大贡献值。通过<strong>拆分</strong>把复杂问题简单化。</li></ul><h3 id="9、二叉树的直径"><a href="#9、二叉树的直径" class="headerlink" title="9、二叉树的直径"></a>9、二叉树的直径</h3><ul><li>描述:给你一棵二叉树的根节点,返回该树的 <strong>直径</strong> 。二叉树的 <strong>直径</strong> 是指树中任意两个节点之间最长路径的 <strong>长度</strong> 。这条路径可能经过也可能不经过根节点 <code>root</code> 。两节点之间路径的 <strong>长度</strong> 由它们之间边数表示。</li></ul><h4 id="解法一:-8"><a href="#解法一:-8" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li><p>思路:直径可以不通过根节点,即答案的最高点可以不是根节点,那么ans就需要在这个过程中不断比较产生。递归得到以当前节点为根的左右两边的最大长度,尝试更新ans,并选取较大的一个返回给上层,这一点跟题目8很像。</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-type">int</span> <span class="hljs-variable">ans</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>;<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">diameterOfBinaryTree</span><span class="hljs-params">(TreeNode root)</span> {<br> dfs(root);<br> <span class="hljs-keyword">return</span> ans - <span class="hljs-number">1</span>;<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">dfs</span><span class="hljs-params">(TreeNode root)</span>{<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">left</span> <span class="hljs-operator">=</span> dfs(root.left) + <span class="hljs-number">1</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">right</span> <span class="hljs-operator">=</span> dfs(root.right) + <span class="hljs-number">1</span>;<br> ans = Math.max(ans, left + right -<span class="hljs-number">1</span>);<br> <span class="hljs-keyword">return</span> Math.max(left, right);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:慢慢自己调出了ac代码,这个过程还是很重要的,对于一些细碎的分类会更加清楚,比如需不需要全局变量,dfs需不需要返回值,+1-1这些判断,自己思考后会很清晰。</li></ul><h3 id="10-验证二叉搜索树"><a href="#10-验证二叉搜索树" class="headerlink" title="10.验证二叉搜索树"></a>10.验证二叉搜索树</h3><ul><li><p>描述:给你一个二叉树的根节点 <code>root</code> ,判断其是否是一个有效的二叉搜索树。</p><p><strong>有效</strong> 二叉搜索树定义如下:</p><ul><li>节点的左子树只包含 <strong>小于</strong> 当前节点的数。</li><li>节点的右子树只包含 <strong>大于</strong> 当前节点的数。</li><li>所有左子树和右子树自身必须也是二叉搜索树。</li></ul></li></ul><h4 id="解法一:-9"><a href="#解法一:-9" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:刚开始暴力的想法就是按照中序遍历的方式保存所有节点信息,再判断是否是一个升序数组,实际上可以直接在递归的过程中逐步地判断,对于当前的每个节点都有上一层传下来的上下界,不符合条件即可返回false。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isValidBST</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">return</span> isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isValidBST</span><span class="hljs-params">(TreeNode root, <span class="hljs-type">long</span> lower, <span class="hljs-type">long</span> upper)</span>{<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> <span class="hljs-keyword">if</span>(root.val <= lower || root.val >= upper) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> <span class="hljs-keyword">return</span> isValidBST(root.left, lower, root.val) && <br> isValidBST(root.right, root.val, upper);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:这个题目的递归顺序没有特别大的要求,主要是传参递归,并且参数是在不断修改的。另外,树上的递归一般都需要一个最先的if判断终止条件,以防递归的无限衍生。</li></ul><h3 id="11-二叉树的层序遍历"><a href="#11-二叉树的层序遍历" class="headerlink" title="11.二叉树的层序遍历"></a>11.二叉树的层序遍历</h3><ul><li>描述:给你二叉树的根节点 <code>root</code> ,返回其节点值的<strong>层序遍历</strong> 。 (即逐层地,从左到右访问所有节点)。</li></ul><h4 id="解法一:-10"><a href="#解法一:-10" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li><p>思路:按照题目按层取出节点值,想到<strong>广度优先搜索</strong>天然符合,通过队列来实现,先考虑左节点再考虑右节点,那么取出来就是每层的从左到右。</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> List<List<Integer>> <span class="hljs-title function_">levelOrder</span><span class="hljs-params">(TreeNode root)</span> {<br> List<List<Integer>> ret = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><>();<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> ret;<br> Queue<TreeNode> queue = <span class="hljs-keyword">new</span> <span class="hljs-title class_">LinkedList</span><>();<br> queue.offer(root);<br> <span class="hljs-keyword">while</span>(!queue.isEmpty()){<br> List<Integer> level = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><>();<br> <span class="hljs-type">int</span> <span class="hljs-variable">curLevelSize</span> <span class="hljs-operator">=</span> queue.size();<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">1</span>; i <= curLevelSize; i++){<br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">node</span> <span class="hljs-operator">=</span> queue.poll();<br> level.add(node.val);<br> <span class="hljs-keyword">if</span>(node.left != <span class="hljs-literal">null</span>) queue.offer(node.left);<br> <span class="hljs-keyword">if</span>(node.right != <span class="hljs-literal">null</span>) queue.offer(node.right);<br> } <br> ret.add(level);<br> }<br> <span class="hljs-keyword">return</span> ret;<br><br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:对于广度优先搜索太久没写了,主要就是用队列,刚开始放一个初始节点,然后非空判断,取出节点又再放入新的节点,并不难。</li></ul><h3 id="12-对称二叉树"><a href="#12-对称二叉树" class="headerlink" title="12.对称二叉树"></a>12.对称二叉树</h3><ul><li>描述:给你一个二叉树的根节点 <code>root</code> , 检查它是否轴对称。</li></ul><h4 id="解法一:-11"><a href="#解法一:-11" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li><p>思路:可以采用<strong>迭代</strong>,利用队列来实现,不断地更新当前的u,v</p></li><li><p>代码:</p></li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isSymmetric</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">return</span> check(root, root);<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">check</span><span class="hljs-params">(TreeNode u, TreeNode v)</span>{<br> Queue<TreeNode> queue = <span class="hljs-keyword">new</span> <span class="hljs-title class_">LinkedList</span><>();<br> queue.offer(u);<br> queue.offer(v);<br> <span class="hljs-keyword">while</span>(!queue.isEmpty()){<br> u = queue.poll();<br> v = queue.poll();<br> <span class="hljs-keyword">if</span>(u == <span class="hljs-literal">null</span> && v == <span class="hljs-literal">null</span>) <span class="hljs-keyword">continue</span>;<br> <span class="hljs-keyword">if</span>(u == <span class="hljs-literal">null</span> || v == <span class="hljs-literal">null</span> || u.val != v.val) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> queue.offer(u.left);<br> queue.offer(v.right);<br> queue.offer(u.right);<br> queue.offer(v.left);<br> }<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:好像用到队列的写法都比较类似,只不过这道题没有涉及广搜的思想,主要就是实现一个迭代,和深搜的递归可以相互转化。</li></ul><h4 id="解法二:-1"><a href="#解法二:-1" class="headerlink" title="解法二:"></a>解法二:</h4><ul><li>思路:采取递归的方式,不断往下迭代。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">isSymmetric</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">return</span> dfs(root, root);<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-type">boolean</span> <span class="hljs-title function_">dfs</span><span class="hljs-params">(TreeNode u, TreeNode v)</span>{<br> <span class="hljs-keyword">if</span>(u == <span class="hljs-literal">null</span> && v == <span class="hljs-literal">null</span> ) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;<br> <span class="hljs-keyword">if</span>(u == <span class="hljs-literal">null</span> || v == <span class="hljs-literal">null</span> || u.val != v.val) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;<br> <span class="hljs-keyword">return</span> dfs(u.left, v.right) && dfs(u.right, v.left);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:很精妙的递归题目,简单的代码即可实现。</li></ul><h3 id="13-翻转二叉树"><a href="#13-翻转二叉树" class="headerlink" title="13.翻转二叉树"></a>13.翻转二叉树</h3><ul><li>描述:给你一棵二叉树的根节点 <code>root</code> ,翻转这棵二叉树,并返回其根节点。</li></ul><h4 id="解法一:-12"><a href="#解法一:-12" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:通过经典的三点交换两个对象的值,然后递归向下逐层进行翻转。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">invertTree</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">tmp</span> <span class="hljs-operator">=</span> root.left;<br> root.left = root.right;<br> root.right = tmp;<br> invertTree(root.left);<br> invertTree(root.right);<br> <span class="hljs-keyword">return</span> root;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:特别的点在于方法虽然有返回值,但是在递归调用时不需要返回值,根据题意就是返回根节点即可,而根节点是不变的,最后原样返回即可。</li></ul><h3 id="14-从前序与中序遍历序列构造二叉树"><a href="#14-从前序与中序遍历序列构造二叉树" class="headerlink" title="14.从前序与中序遍历序列构造二叉树"></a>14.从前序与中序遍历序列构造二叉树</h3><ul><li>描述:给定两个整数数组 <code>preorder</code> 和 <code>inorder</code> ,其中 <code>preorder</code> 是二叉树的<strong>先序遍历</strong>, <code>inorder</code> 是同一棵树的<strong>中序遍历</strong>,请构造二叉树并返回其根节点。</li></ul><h4 id="解法一:-13"><a href="#解法一:-13" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:前序与中序遍历相结合,通过前序遍历找到根节点,再通过该根节点在中序遍历中找到左子树的大小,进而回到前序遍历找到新的根,不断向下递归实现整棵二叉树的构造。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">private</span> Map<Integer, Integer> indexMap;<br> <span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">myBuildTree</span><span class="hljs-params">(<span class="hljs-type">int</span>[] preorder, <span class="hljs-type">int</span>[] inorder, <span class="hljs-type">int</span> pl, <span class="hljs-type">int</span> pr, <span class="hljs-type">int</span> il, <span class="hljs-type">int</span> ir)</span>{<br> <span class="hljs-keyword">if</span>(pl > pr) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">p_root</span> <span class="hljs-operator">=</span> pl;<br> <span class="hljs-type">int</span> <span class="hljs-variable">i_root</span> <span class="hljs-operator">=</span> indexMap.get(preorder[p_root]);<br><br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">root</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">TreeNode</span>(preorder[p_root]);<br> <span class="hljs-type">int</span> <span class="hljs-variable">size_left_subtree</span> <span class="hljs-operator">=</span> i_root - il;<br> root.left = myBuildTree(preorder, inorder, pl + <span class="hljs-number">1</span>, pl + size_left_subtree, il, ir -<span class="hljs-number">1</span>);<br> root.right = myBuildTree(preorder, inorder, pl + size_left_subtree + <span class="hljs-number">1</span>, pr, i_root + <span class="hljs-number">1</span>, ir);<br> <span class="hljs-keyword">return</span> root;<br> }<br> <span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">buildTree</span><span class="hljs-params">(<span class="hljs-type">int</span>[] preorder, <span class="hljs-type">int</span>[] inorder)</span> {<br> <span class="hljs-type">int</span> <span class="hljs-variable">n</span> <span class="hljs-operator">=</span> preorder.length;<br> indexMap = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><Integer,Integer>();<br> <span class="hljs-keyword">for</span>(<span class="hljs-type">int</span> <span class="hljs-variable">i</span> <span class="hljs-operator">=</span> <span class="hljs-number">0</span>; i < n; i++){<br> indexMap.put(inorder[i], i);<br> }<br> <span class="hljs-keyword">return</span> myBuildTree(preorder, inorder, <span class="hljs-number">0</span>, n - <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, n - <span class="hljs-number">1</span>);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:找到其中可递归的部分,两个数组交相更新,很巧妙的一个出题思路。同时,利用了<strong>Map</strong>数据结构,快速找到其中的值的坐标。</li></ul><h3 id="15-打家劫舍"><a href="#15-打家劫舍" class="headerlink" title="15.打家劫舍|||"></a>15.打家劫舍|||</h3><ul><li><p>描述:小偷又发现了一个新的可行窃的地区。这个地区只有一个入口,我们称之为 <code>root</code> 。</p><p>除了 <code>root</code> 之外,每栋房子有且只有一个“父“房子与之相连。一番侦察之后,聪明的小偷意识到“这个地方的所有房屋的排列类似于一棵二叉树”。 如果 <strong>两个直接相连的房子在同一天晚上被打劫</strong> ,房屋将自动报警。</p><p>给定二叉树的 <code>root</code> 。返回 <strong>在不触动警报的情况下</strong> ,小偷能够盗取的最高金额 。</p></li></ul><h4 id="解法一:-14"><a href="#解法一:-14" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:是一个<strong>树形DP</strong>问题,每个节点有选(f)或不选(g)两种选择,自底向上看的话,f(node) = node.val+g(node.left)+g(node.right),g(node)=max(g(node.left),f(node.left))+max(g(node.right),f(node.right))。先递归再处理值的转移,就形成<strong>自底向上的推导</strong>。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> Map<TreeNode, Integer> f = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><>();<br> Map<TreeNode, Integer> g = <span class="hljs-keyword">new</span> <span class="hljs-title class_">HashMap</span><>();<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">rob</span><span class="hljs-params">(TreeNode root)</span> {<br> dfs(root);<br> <span class="hljs-keyword">return</span> Math.max(f.getOrDefault(root,<span class="hljs-number">0</span>), g.getOrDefault(root,<span class="hljs-number">0</span>));<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">dfs</span><span class="hljs-params">(TreeNode node)</span>{<br> <span class="hljs-keyword">if</span>(node == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>;<br> dfs(node.left);<br> dfs(node.right);<br> f.put(node,node.val + g.getOrDefault(node.left,<span class="hljs-number">0</span>) + g.getOrDefault(node.right,<span class="hljs-number">0</span>));<br> g.put(node, Math.max(f.getOrDefault(node.left, <span class="hljs-number">0</span>),g.getOrDefault(node.left, <span class="hljs-number">0</span>))<br> +Math.max(f.getOrDefault(node.right, <span class="hljs-number">0</span>),g.getOrDefault(node.right, <span class="hljs-number">0</span>)));<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:第一眼都没看出来是动态规划。其实是个比较常见的自底向上的套路,推导公式也比较正常,结合Map实现,多多练习吧。</li></ul><h4 id="解法二:-2"><a href="#解法二:-2" class="headerlink" title="解法二:"></a>解法二:</h4><ul><li>思路:解法一的代码可以发现f,g和总是依赖上一层的结果,没必要记录所有的过程,可以对此进行优化,利用数组记录每次的结果即可。</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">rob</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-type">int</span>[] rootStatus = dfs(root);<br> <span class="hljs-keyword">return</span> Math.max(rootStatus[<span class="hljs-number">0</span>], rootStatus[<span class="hljs-number">1</span>]);<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span>[] dfs(TreeNode node){<br> <span class="hljs-keyword">if</span>(node == <span class="hljs-literal">null</span>){<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">int</span>[]{<span class="hljs-number">0</span>, <span class="hljs-number">0</span>};<br> }<br> <span class="hljs-type">int</span>[] l = dfs(node.left);<br> <span class="hljs-type">int</span>[] r = dfs(node.right);<br> <span class="hljs-type">int</span> <span class="hljs-variable">select</span> <span class="hljs-operator">=</span> node.val + l[<span class="hljs-number">1</span>] + r[<span class="hljs-number">1</span>];<br> <span class="hljs-type">int</span> <span class="hljs-variable">noSelect</span> <span class="hljs-operator">=</span> Math.max(l[<span class="hljs-number">0</span>], l[<span class="hljs-number">1</span>]) + Math.max(r[<span class="hljs-number">0</span>], r[<span class="hljs-number">1</span>]);<br> <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">int</span>[]{select, noSelect};<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:利用数组的两个元素进行优化,代码原理基本一致,dfs有了返回值,相同的思路不一样的写法,That‘s cool.</li></ul><h3 id="16-二叉树的中序遍历"><a href="#16-二叉树的中序遍历" class="headerlink" title="16.二叉树的中序遍历"></a>16.二叉树的中序遍历</h3><ul><li>描述:给定一个二叉树的根节点 <code>root</code> ,返回 <em>它的 <strong>中序</strong> 遍历</em> 。</li></ul><h4 id="解法一:-15"><a href="#解法一:-15" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:中序遍历即按照<strong>左子树、根节点、右子树</strong>的顺序<strong>递归</strong>遍历整棵二叉树</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> List<Integer> res = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><>();<br> <span class="hljs-keyword">public</span> List<Integer> <span class="hljs-title function_">inorderTraversal</span><span class="hljs-params">(TreeNode root)</span> {<br> dfs(root);<br> <span class="hljs-keyword">return</span> res;<br> }<br> <span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title function_">dfs</span><span class="hljs-params">(TreeNode root)</span>{<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span>;<br> dfs(root.left);<br> res.add(root.val);<br> dfs(root.right);<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:分析dfs特点,选择设定一个全局变量,dfs不需要返回值。自己敲出来了,算是对树的递归入了门啦。当然,也可以把res作为一个参数传入到dfs中,是一样的效果。</li></ul><h4 id="解法二:-3"><a href="#解法二:-3" class="headerlink" title="解法二:"></a>解法二:</h4><ul><li>思路:使用<strong>迭代</strong>的思维,维护一个<strong>栈</strong>,先后加入左子树,直到不能加入为止,再加入根节点,再加入右子树,回到之前的步骤</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> List<Integer> <span class="hljs-title function_">inorderTraversal</span><span class="hljs-params">(TreeNode root)</span> {<br> List<Integer> res = <span class="hljs-keyword">new</span> <span class="hljs-title class_">ArrayList</span><>();<br> Deque<TreeNode> stk = <span class="hljs-keyword">new</span> <span class="hljs-title class_">LinkedList</span><>();<br> <span class="hljs-keyword">while</span>(root != <span class="hljs-literal">null</span> || !stk.isEmpty()){<br> <span class="hljs-keyword">while</span>(root != <span class="hljs-literal">null</span>){<br> stk.push(root);<br> root = root.left;<br> }<br> root = stk.pop();<br> res.add(root.val);<br> root = root.right;<br> }<br> <span class="hljs-keyword">return</span> res;<br><br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:递归和迭代在很多时候可以相互转换,相对来说,对迭代更加不熟悉,需要多加练习。大部分是结合栈来实现,如第1题,但第12题对称二叉树采用了队列实现。</li></ul><h3 id="17-二叉树的最大深度"><a href="#17-二叉树的最大深度" class="headerlink" title="17.二叉树的最大深度"></a>17.二叉树的最大深度</h3><ul><li>描述:给定一个二叉树 <code>root</code> ,返回其最大深度。二叉树的 <strong>最大深度</strong> 是指从根节点到最远叶子节点的最长路径上的节点数。</li></ul><h4 id="解法一:-16"><a href="#解法一:-16" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:很递归的一道题目,左右子树的最大深度又可以决定当前的最大深度</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">class</span> <span class="hljs-title class_">Solution</span> {<br> <span class="hljs-keyword">public</span> <span class="hljs-type">int</span> <span class="hljs-title function_">maxDepth</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;<br> <span class="hljs-type">int</span> <span class="hljs-variable">l</span> <span class="hljs-operator">=</span> maxDepth(root.left);<br> <span class="hljs-type">int</span> <span class="hljs-variable">r</span> <span class="hljs-operator">=</span> maxDepth(root.right);<br> <span class="hljs-keyword">return</span> Math.max(l,r) + <span class="hljs-number">1</span>;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:递归很清晰的一道题目,算是很多题目的源头叭~</li></ul><h3 id="18-二叉树的序列化和反序列化"><a href="#18-二叉树的序列化和反序列化" class="headerlink" title="18.二叉树的序列化和反序列化"></a>18.二叉树的序列化和反序列化</h3><ul><li><p>描述:序列化是将一个数据结构或者对象转换为连续的比特位的操作,进而可以将转换后的数据存储在一个文件或者内存中,同时也可以通过网络传输到另一个计算机环境,采取相反方式重构得到原数据。</p><p>请设计一个算法来实现二叉树的序列化与反序列化。这里不限定你的序列 / 反序列化算法执行逻辑,只需要保证一个二叉树可以被序列化为一个字符串并且将这个字符串反序列化为原始的树结构。</p></li></ul><h4 id="解法一:-17"><a href="#解法一:-17" class="headerlink" title="解法一:"></a>解法一:</h4><ul><li>思路:可以按照先序遍历取出二叉树上的值,空节点用None代替,然后再把List类型递归按先序遍历生成二叉树</li><li>代码:</li></ul><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><code class="hljs java"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title class_">Codec</span> {<br> <span class="hljs-keyword">public</span> String <span class="hljs-title function_">serialize</span><span class="hljs-params">(TreeNode root)</span> {<br> <span class="hljs-keyword">return</span> rserialize(root, <span class="hljs-string">""</span>);<br> }<br> <span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">deserialize</span><span class="hljs-params">(String data)</span> {<br> String[] dataArray = data.split(<span class="hljs-string">","</span>);<br> List<String> dataList = <span class="hljs-keyword">new</span> <span class="hljs-title class_">LinkedList</span><String>(Arrays.asList(dataArray));<br> <span class="hljs-keyword">return</span> rdeserialize(dataList); <br> }<br> <span class="hljs-keyword">public</span> String <span class="hljs-title function_">rserialize</span><span class="hljs-params">(TreeNode root, String str)</span>{<br> <span class="hljs-keyword">if</span>(root == <span class="hljs-literal">null</span>){<br> str += <span class="hljs-string">"None,"</span>;<br> }<span class="hljs-keyword">else</span>{<br> str += str.valueOf(root.val) + <span class="hljs-string">","</span>;<br> str = rserialize(root.left, str);<br> str = rserialize(root.right, str);<br> }<br> <span class="hljs-keyword">return</span> str;<br> }<br> <span class="hljs-keyword">public</span> TreeNode <span class="hljs-title function_">rdeserialize</span><span class="hljs-params">(List<String> dataList)</span>{<br> <span class="hljs-keyword">if</span>(dataList.get(<span class="hljs-number">0</span>).equals(<span class="hljs-string">"None"</span>)){<br> dataList.remove(<span class="hljs-number">0</span>);<br> <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;<br> }<br> <span class="hljs-type">TreeNode</span> <span class="hljs-variable">root</span> <span class="hljs-operator">=</span> <span class="hljs-keyword">new</span> <span class="hljs-title class_">TreeNode</span>(Integer.valueOf(dataList.get(<span class="hljs-number">0</span>)));<br> dataList.remove(<span class="hljs-number">0</span>);<br> root.left = rdeserialize(dataList);<br> root.right = rdeserialize(dataList);<br> <span class="hljs-keyword">return</span> root;<br> }<br>}<br></code></pre></td></tr></table></figure><ul><li>总结:相当于两个简单题的组合,读取二叉树和将有序数组转化为二叉树,还有一些字符串的应用,比如valueOf,split方法</li></ul>]]></content>
<categories>
<category>算法</category>
</categories>
<tags>
<tag>二叉树</tag>
</tags>
</entry>
<entry>
<title>课设复盘</title>
<link href="/2024/01/19/%E6%A0%A1%E5%86%85%E5%AD%A6%E4%B9%A0/%E8%AF%BE%E8%AE%BE%E5%A4%8D%E7%9B%98/"/>
<url>/2024/01/19/%E6%A0%A1%E5%86%85%E5%AD%A6%E4%B9%A0/%E8%AF%BE%E8%AE%BE%E5%A4%8D%E7%9B%98/</url>
<content type="html"><![CDATA[<h1 id="大三上两次课程设计复盘"><a href="#大三上两次课程设计复盘" class="headerlink" title="大三上两次课程设计复盘"></a>大三上两次课程设计复盘</h1><h4 id="1-数据库管理系统课设"><a href="#1-数据库管理系统课设" class="headerlink" title="1.数据库管理系统课设"></a>1.数据库管理系统课设</h4><ul><li><strong>Situation:</strong> 情景。 事情是在什么情况下发生的?<ul><li>6个人的小组,需要完成一个数据库管理系统,包括文件结构存储,实现DDL,DML语句。</li></ul></li><li><strong>Task:</strong> 任务。你的任务是什么?<ul><li>担任组长</li><li>挑选合适的项目作为开发基础</li><li>对任务进行分工,包括从开发任务到汇报文档</li></ul></li><li><strong>Action:</strong> 行动。你做了什么?<ul><li>刚开始选择MYDB作为项目基础,但是其实现更偏原理性,可用性不强,且理解难度高,故舍弃</li><li>理解现有项目的实现,和组员讨论在此基础上要扩充的内容</li><li>合理分配任务,自己选择最难的select语句实现</li><li>帮助组员解决技术卡克点</li><li>制作ppt,向老师进行汇报答辩</li></ul></li><li><strong>Result:</strong> 结果。最终的结果怎样?<ul><li>既定的任务实现了90%,没有实现的是预先没有直接分配的那个任务</li><li>实现了前端界面和所有基本语句的支持,项目比较完整</li><li>答辩汇报也比较顺利,问答环节每个人回答到位</li></ul></li><li><strong>收获:</strong><ul><li>此次的专业技能提升主要在于编写select语句上,大力出奇迹的感觉,第一次真正用编码解决实际问题,虽然其实现性较为有限</li><li>软实力提升了不少,包括和组员共同能力,对整个项目进度的掌控能力,以及最后汇报的表达能力,均得到了提升</li></ul></li></ul><h4 id="2-软件文档-人脸识别Android-app课设"><a href="#2-软件文档-人脸识别Android-app课设" class="headerlink" title="2.软件文档-人脸识别Android app课设"></a>2.软件文档-人脸识别Android app课设</h4><ul><li><strong>Situation:</strong> 情景。 事情是在什么情况下发生的?<ul><li>需要开发一个系统实现人脸识别考勤签到,教师学生信息管理以及权限管理系统</li></ul></li><li><strong>Task:</strong> 任务。你的任务是什么?<ul><li>协助组长,帮助其推进项目</li></ul></li><li><strong>Action:</strong> 行动。你做了什么?<ul><li>最开始选择基础项目,敲定使用一个功能比较全的app项目</li><li>最近项目环境配置,一直不成功,在网上联系技术专家解决</li><li>最后项目部署上线,协助组长</li><li>一些文档编写,包括ER图的绘制</li></ul></li><li><strong>Result:</strong> 结果。最终的结果怎样?<ul><li>是唯一一个把app做出来的小组 ,其他都是网页版的实现,实现部分拿到了满分</li></ul></li><li><strong>收获:</strong><ul><li>专业技术:ER图建模,对关系型数据库建模的逻辑性有了更深的理解;Android项目的基本认识;项目部署上线流程有了大致的了解。</li><li>软能力:<ul><li>对一个更大项目的整体实现的认识,从各种文档的编写,前期需求分析,到ER图建模,项目选型,技术实现,部署上线,有了一个更加直观的体验;</li><li>学习到一些组织一个8人小组的经验</li></ul></li></ul></li></ul>]]></content>
<categories>
<category>项目</category>
</categories>
<tags>
<tag>学校项目</tag>
</tags>
</entry>
<entry>
<title>测试文章</title>
<link href="/2024/01/19/%E7%94%9F%E6%B4%BB%E4%B8%8E%E6%8A%80%E6%9C%AF/%E6%B5%8B%E8%AF%95%E6%96%87%E7%AB%A0/"/>
<url>/2024/01/19/%E7%94%9F%E6%B4%BB%E4%B8%8E%E6%8A%80%E6%9C%AF/%E6%B5%8B%E8%AF%95%E6%96%87%E7%AB%A0/</url>
<content type="html"><![CDATA[<p> 这是一篇测试文章:</p><img src="/2024/01/19/%E7%94%9F%E6%B4%BB%E4%B8%8E%E6%8A%80%E6%9C%AF/%E6%B5%8B%E8%AF%95%E6%96%87%E7%AB%A0/test.png" class="" title="图片引用方法一">]]></content>
</entry>
</search>