-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
2084 lines (1797 loc) · 385 KB
/
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
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>vue中的生命周期钩子函数</title>
<url>/2024/06/17/vue%E4%B8%AD%E7%9A%84%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E9%92%A9%E5%AD%90%E5%87%BD%E6%95%B0/</url>
<content><![CDATA[<h1 id="vue中的生命周期钩子函数"><a href="#vue中的生命周期钩子函数" class="headerlink" title="vue中的生命周期钩子函数"></a>vue中的生命周期钩子函数</h1><p>在 Vue 3 中,生命周期函数总体上经历了一些改变,并引入了 Composition API,与 Vue 2.x 中的选项 API 有所不同。以下是 Vue 3 中常用的生命周期函数:</p>
<ol>
<li><p><strong>setup</strong>:组件创建阶段的入口,在组件实例创建之前执行,用于设置组件的初始状态、逻辑以及副作用操作等。</p>
</li>
<li><p><strong>beforeCreate</strong>:与 Vue 2.x 中的 <code>beforeCreate</code> 类似,在组件实例初始化之后,数据观测之前被调用。</p>
</li>
<li><p><strong>created</strong>:与 Vue 2.x 中的 <code>created</code> 类似,在实例创建完成后被调用,实例已完成数据观测、属性和方法运算。</p>
</li>
<li><p><strong>beforeMount</strong>:与 Vue 2.x 中的 <code>beforeMount</code> 类似,在挂载开始之前被调用,相关的 render 函数首次调用。</p>
</li>
<li><p><strong>mounted</strong>:与 Vue 2.x 中的 <code>mounted</code> 类似,在挂载结束后被调用,实例已挂载到 DOM 上。</p>
</li>
<li><p><strong>beforeUpdate</strong>:当数据更改导致虚拟 DOM 重新渲染之前调用。</p>
</li>
<li><p><strong>updated</strong>:当数据更改导致虚拟 DOM 重新渲染和打补丁后调用。</p>
</li>
<li><p><strong>beforeUnmount</strong>:在卸载组件之前调用。</p>
</li>
<li><p><strong>unmounted</strong>:在卸载组件后调用。</p>
</li>
<li><p><strong>errorCaptured</strong>:捕获组件子树中任何错误的处理器。</p>
</li>
</ol>
<p>除了上述生命周期函数外,Vue 3 还引入了 Composition API,开发者可以使用 <code>onMounted</code>、<code>onUpdated</code>、<code>onUnmounted</code> 等函数来实现类似生命周期钩子的功能。Composition API 提供了更灵活的方式来组织组件的逻辑。请注意,Vue 3 中的生命周期钩子函数与 Vue 2.x 中可能略有差异,主要是由于引入了 Composition API 的改变。</p>
]]></content>
<tags>
<tag>Vue3</tag>
</tags>
</entry>
<entry>
<title>使用线性渐变实现渐变背景</title>
<url>/2024/06/17/%E4%BD%BF%E7%94%A8%E7%BA%BF%E6%80%A7%E6%B8%90%E5%8F%98%E5%AE%9E%E7%8E%B0%E6%B8%90%E5%8F%98%E8%83%8C%E6%99%AF/</url>
<content><![CDATA[<h1 id="使用线性渐变实现渐变背景"><a href="#使用线性渐变实现渐变背景" class="headerlink" title="使用线性渐变实现渐变背景"></a>使用线性渐变实现渐变背景</h1><figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="attribute">background-image</span>: <span class="built_in">linear-gradient</span>(<span class="number">270deg</span>, <span class="number">#f66</span>, <span class="number">#ff9f9f</span>);</span><br></pre></td></tr></table></figure>
<p>这段CSS代码是用于设置元素的背景图片,但是这里使用的不是传统的图像文件,而是通过线性渐变(linear gradient)来实现背景效果。让我们来解释一下这段代码的含义:</p>
<ol>
<li><p><strong><code>background-image:</code></strong> 这是CSS属性,用于设置元素的背景图片。</p>
</li>
<li><p><strong><code>linear-gradient(270deg, #f66, #ff9f9f);</code></strong> 这是具体的背景图片值,表示使用线性渐变(从一个颜色过渡到另一个颜色)来创建背景。</p>
</li>
</ol>
<ul>
<li><p><strong><code>270deg</code></strong> 表示指定线性渐变的方向为270度,即从底部到顶部的垂直方向。</p>
</li>
<li><p><strong><code>#f66</code></strong> 和 <strong><code>#ff9f9f</code></strong> 是渐变的起始色和结束色。第一个颜色 <code>#f66</code> 代表浅红色,第二个是 <code>#ff9f9f</code> 代表淡红色。在这种情况下,从底部到顶部的背景将逐渐从浅红色过渡到淡红色。</p>
</li>
</ul>
<p>所以,这段代码的意思是设置元素的背景为从底部到顶部的垂直线性渐变,颜色过渡从浅红色(<code>#f66</code>)到淡红色(<code>#ff9f9f</code>)。这样的效果会创建一个具有渐变色的背景,使元素看起来更加丰富和动态。</p>
]]></content>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title>Flex布局与Grid布局</title>
<url>/2024/06/17/Flex%E5%B8%83%E5%B1%80%E4%B8%8EGrid%E5%B8%83%E5%B1%80/</url>
<content><![CDATA[<h1 id="Flex布局与Grid布局"><a href="#Flex布局与Grid布局" class="headerlink" title="Flex布局与Grid布局"></a>Flex布局与Grid布局</h1><p>Grid布局和Flex布局都是在CSS中用于进行页面布局的工具,它们各有优势和适用场景。以下是它们的一些异同点以及优缺点:</p>
<p><strong>异同点:</strong></p>
<ol>
<li><p><strong>相同点:</strong></p>
<ul>
<li>两者都是现代CSS布局工具,用于实现响应式布局和页面排版。</li>
<li>都支持对网格和弹性盒子进行灵活布局。</li>
<li>都可以在容器内部的子元素之间创建空间布局。</li>
</ul>
</li>
<li><p><strong>不同点:</strong></p>
<ul>
<li><p><strong>Flex布局(弹性布局):</strong></p>
<ul>
<li>适用于一维布局,例如在一条水平或垂直的轴线上布局元素。</li>
<li>适合于构建灵活的、水平或垂直居中的布局。</li>
<li>可以根据内容的大小来调整元素的尺寸。</li>
</ul>
</li>
<li><p><strong>Grid布局(网格布局):</strong></p>
<ul>
<li>适用于二维布局,可以在交叉轴上对元素进行定位,创建复杂的网格布局。</li>
<li>适用于规划复杂的网格结构,如页面布局的整体设计。</li>
<li>可以控制行与列交叉点的位置,实现更精确的布局设计。</li>
</ul>
</li>
</ul>
</li>
</ol>
<p><strong>优缺点:</strong></p>
<ol>
<li><p><strong>Flex布局优点:</strong></p>
<ul>
<li>简单实用,适合搭建基本的布局和页面结构。</li>
<li>支持响应式布局,更容易实现移动端适配,适合移动端开发。</li>
<li>配合弹性盒子布局的属性丰富,可以快速实现元素的排列和对齐。</li>
</ul>
<p><strong>缺点:</strong></p>
<ul>
<li>适用于相对简单布局,复杂的网格结构可能实现起来比较困难。</li>
<li>不太适合搭建复杂的多列布局。</li>
</ul>
</li>
<li><p><strong>Grid布局优点:</strong></p>
<ul>
<li>可以实现更复杂的网格布局,可以精确控制元素的位置和大小。</li>
<li>适合搭建大型网站和复杂的设计布局。</li>
<li>支持分区和定位,可以创建更灵活的页面结构。</li>
</ul>
<p><strong>缺点:</strong></p>
<ul>
<li>学习成本相对较高,语法相对复杂,初学者可能需要一定时间适应。</li>
<li>在一维布局方面不如Flex布局灵活,并不适用于所有布局场景。</li>
</ul>
</li>
</ol>
<p><strong>结论:</strong> </p>
<ul>
<li>如果页面结构相对简单,主要涉及到一维布局的元素排列和对齐,Flex布局是一个不错的选择。</li>
<li>如果需要实现复杂的二维布局,例如创建大型网格结构,Grid布局更适合用来实现。</li>
<li>在实际项目中,可以根据具体需求和布局复杂度来选择合适的布局方法,有时候也可以结合使用两者来实现更灵活和多样化的布局效果。</li>
</ul>
]]></content>
<categories>
<category>CSS</category>
</categories>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title>文本的截断和显示控制</title>
<url>/2024/06/16/%E6%96%87%E6%9C%AC%E7%9A%84%E6%88%AA%E6%96%AD%E5%92%8C%E6%98%BE%E7%A4%BA%E6%8E%A7%E5%88%B6/</url>
<content><![CDATA[<h1 id="文本的截断和显示控制"><a href="#文本的截断和显示控制" class="headerlink" title="文本的截断和显示控制"></a>文本的截断和显示控制</h1><p>下面三个属性通常用于在Web开发中对文本进行截断和显示控制,主要用于控制文本在容器中的显示方式。具体含义如下:</p>
<ol>
<li><p><code>display: -webkit-box;</code>:这个属性用于指定元素应该生成一个块级容器框。在这种布局模型中,元素是一个块级容器,可以在内部容纳其他元素。在这种情况下,通常需要与其他属性结合使用。</p>
</li>
<li><p><code>-webkit-line-clamp: 2;</code>:这个属性用于指定显示的行数限制。在文本溢出时,只显示指定行数的文本内容。上面的例子中,只显示不超过两行的文本内容。</p>
</li>
<li><p><code> -webkit-box-orient: vertical;</code>:这个属性用于指定盒子的排列方向。在这种情况下,盒子内的元素垂直排列。</p>
</li>
</ol>
<p>这些属性通常与前缀 <code>-webkit-</code> 一起使用,表示这些属性是Webkit浏览器专有的CSS扩展。这些属性主要用于控制元素的显示方式,特别是在限制文本显示行数和盒子内元素排列方向方面。</p>
]]></content>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title>text-overflow的用法</title>
<url>/2024/06/14/text-overflow%E7%9A%84%E7%94%A8%E6%B3%95/</url>
<content><![CDATA[<h1 id="text-overflow的用法"><a href="#text-overflow的用法" class="headerlink" title="text-overflow的用法"></a>text-overflow的用法</h1><p><code>text-overflow</code>是CSS样式属性,用于控制当文本溢出容器时如何显示。</p>
<p>常见的取值有:</p>
<ul>
<li><code>clip</code>:默认值,表示将溢出的部分隐藏。</li>
<li><code>ellipsis</code>:表示将溢出的文本显示为省略号(…)。</li>
<li><code>inherit</code>:继承父元素的文本溢出样式。</li>
</ul>
<p>示例:</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.text-ellipsis</span> {</span><br><span class="line"> <span class="attribute">white-space</span>: nowrap; <span class="comment">/* 不换行 */</span></span><br><span class="line"> <span class="attribute">overflow</span>: hidden; <span class="comment">/* 溢出隐藏 */</span></span><br><span class="line"> <span class="attribute">text-overflow</span>: ellipsis; <span class="comment">/* 超出部分以省略号显示 */</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>在上面的示例中,当文本内容超出容器的宽度时,将以省略号的形式显示。需要注意的是,通常需要配合<code>white-space: nowrap;</code>和<code>overflow: hidden;</code>这两个样式属性一起使用,来确保省略号的效果正常显示。</p>
<p><code>text-overflow</code>通常用于单行文本或者内联元素,对于多行文本或块级元素,更适合使用<code>-webkit-line-clamp</code>结合<code>-webkit-box</code>来实现类似的效果。</p>
]]></content>
</entry>
<entry>
<title>less中的&符号</title>
<url>/2024/06/14/less%E4%B8%AD%E7%9A%84&%E7%AC%A6%E5%8F%B7/</url>
<content><![CDATA[<h1 id="less中的-amp-符号"><a href="#less中的-amp-符号" class="headerlink" title="less中的&符号"></a>less中的&符号</h1><p>在 Less 预处理器中,<code>&</code> 符号用于引用当前选择器的父级。这在嵌套规则中非常有用,可以帮助生成更复杂的选择器,而不需要重复父选择器的名称。</p>
<h3 id="基本用法"><a href="#基本用法" class="headerlink" title="基本用法"></a>基本用法</h3><p>在 Less 中,<code>&</code> 符号代表父选择器,可以用来构建更复杂的选择器规则。例如:</p>
<figure class="highlight less"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">color</span>: black;</span><br><span class="line"> </span><br><span class="line"> <span class="selector-tag">&</span><span class="selector-pseudo">:hover</span> {</span><br><span class="line"> <span class="attribute">color</span>: blue;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="selector-tag">&</span><span class="selector-pseudo">::before</span> {</span><br><span class="line"> <span class="attribute">content</span>: <span class="string">"Prefix"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>编译后的 CSS 如下:</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">color</span>: black;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.container</span><span class="selector-pseudo">:hover</span> {</span><br><span class="line"> <span class="attribute">color</span>: blue;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.container</span><span class="selector-pseudo">::before</span> {</span><br><span class="line"> <span class="attribute">content</span>: <span class="string">"Prefix"</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h3 id="具体示例"><a href="#具体示例" class="headerlink" title="具体示例"></a>具体示例</h3><p>以下是一些常见的 <code>&</code> 符号用法示例:</p>
<h4 id="1-伪类和伪元素"><a href="#1-伪类和伪元素" class="headerlink" title="1. 伪类和伪元素"></a>1. 伪类和伪元素</h4><figure class="highlight less"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.button</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: green;</span><br><span class="line"> </span><br><span class="line"> <span class="selector-tag">&</span><span class="selector-pseudo">:hover</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: darkgreen;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="selector-tag">&</span><span class="selector-pseudo">::after</span> {</span><br><span class="line"> <span class="attribute">content</span>: <span class="string">" (hover me)"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>编译后的 CSS:</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.button</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: green;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.button</span><span class="selector-pseudo">:hover</span> {</span><br><span class="line"> <span class="attribute">background-color</span>: darkgreen;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.button</span><span class="selector-pseudo">::after</span> {</span><br><span class="line"> <span class="attribute">content</span>: <span class="string">" (hover me)"</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="2-子选择器"><a href="#2-子选择器" class="headerlink" title="2. 子选择器"></a>2. 子选择器</h4><figure class="highlight less"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.nav</span> {</span><br><span class="line"> <span class="selector-tag">&</span><span class="selector-tag">-item</span> {</span><br><span class="line"> <span class="attribute">color</span>: red;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>编译后的 CSS:</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.nav-item</span> {</span><br><span class="line"> <span class="attribute">color</span>: red;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="3-父选择器引用"><a href="#3-父选择器引用" class="headerlink" title="3. 父选择器引用"></a>3. 父选择器引用</h4><figure class="highlight less"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.list</span> {</span><br><span class="line"> <span class="selector-class">.list-item</span> {</span><br><span class="line"> <span class="attribute">color</span>: blue;</span><br><span class="line"> </span><br><span class="line"> <span class="selector-tag">&</span><span class="selector-class">.active</span> {</span><br><span class="line"> <span class="attribute">color</span>: darkblue;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>编译后的 CSS:</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.list</span> <span class="selector-class">.list-item</span> {</span><br><span class="line"> <span class="attribute">color</span>: blue;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.list</span> <span class="selector-class">.list-item</span><span class="selector-class">.active</span> {</span><br><span class="line"> <span class="attribute">color</span>: darkblue;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h4 id="4-嵌套媒体查询"><a href="#4-嵌套媒体查询" class="headerlink" title="4. 嵌套媒体查询"></a>4. 嵌套媒体查询</h4><figure class="highlight less"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">@media</span> (<span class="attribute">min-width</span>: <span class="number">768px</span>) {</span><br><span class="line"> <span class="selector-tag">&</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">50%</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>编译后的 CSS:</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line">}</span><br><span class="line"><span class="keyword">@media</span> (<span class="attribute">min-width</span>: <span class="number">768px</span>) {</span><br><span class="line"> <span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">50%</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h3 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h3><p><code>&</code> 符号在 Less 中非常强大,可以帮助你避免重复代码,并使样式表更具可读性和可维护性。通过合理使用 <code>&</code> 符号,可以轻松创建复杂的选择器规则,提升 CSS 编写的效率和灵活性。</p>
]]></content>
<tags>
<tag>Less</tag>
</tags>
</entry>
<entry>
<title>overflow的用法</title>
<url>/2024/06/14/overflow%E7%9A%84%E7%94%A8%E6%B3%95/</url>
<content><![CDATA[<h1 id="Overflow的用法"><a href="#Overflow的用法" class="headerlink" title="Overflow的用法"></a>Overflow的用法</h1><p><code>overflow</code> 是 CSS 中的一个属性,用于控制元素内容在水平方向和垂直方向上的溢出行为。它决定了当内容溢出元素的尺寸时,是否显示滚动条、截断内容或其他处理方式。</p>
<h3 id="语法"><a href="#语法" class="headerlink" title="语法"></a>语法</h3><figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="attribute">overflow</span>: visible | hidden | scroll | auto;</span><br></pre></td></tr></table></figure>
<h3 id="属性值"><a href="#属性值" class="headerlink" title="属性值"></a>属性值</h3><ul>
<li><code>visible</code>:默认值。内容不会被剪裁,会呈现在元素框之外。</li>
<li><code>hidden</code>:溢出内容会被剪裁(隐藏),不会显示滚动条。</li>
<li><code>scroll</code>:无论内容是否溢出,都会显示滚动条。</li>
<li><code>auto</code>:如果内容溢出,浏览器会自动显示滚动条。</li>
</ul>
<h3 id="示例"><a href="#示例" class="headerlink" title="示例"></a>示例</h3><p>假设有一个包含大量文本的容器:</p>
<figure class="highlight html"><table><tr><td class="code"><pre><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"container"</span>></span></span><br><span class="line"> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse varius enim in eros elementum tristique.</span><br><span class="line"><span class="tag"></<span class="name">div</span>></span></span><br></pre></td></tr></table></figure>
<p>CSS 代码如下:</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid black;</span><br><span class="line"> <span class="attribute">overflow</span>: auto; <span class="comment">/* 自动显示滚动条 */</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>在这个例子中:</p>
<ul>
<li>当容器的内容宽度或高度超过 200px 或 100px 时,浏览器会自动显示水平或垂直滚动条,以便用户可以滚动查看内容。</li>
</ul>
<h3 id="各属性值示例"><a href="#各属性值示例" class="headerlink" title="各属性值示例"></a>各属性值示例</h3><ol>
<li><code>visible</code>:</li>
</ol>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid black;</span><br><span class="line"> <span class="attribute">overflow</span>: visible;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>内容会溢出容器,不会显示滚动条。</p>
<ol start="2">
<li><code>hidden</code>:</li>
</ol>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid black;</span><br><span class="line"> <span class="attribute">overflow</span>: hidden;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>内容会被剪裁,溢出部分不可见,不会显示滚动条。</p>
<ol start="3">
<li><code>scroll</code>:</li>
</ol>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid black;</span><br><span class="line"> <span class="attribute">overflow</span>: scroll;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>无论内容是否溢出,都会显示滚动条。</p>
<ol start="4">
<li><code>auto</code>:</li>
</ol>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid black;</span><br><span class="line"> <span class="attribute">overflow</span>: auto;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<p>当内容溢出时,浏览器会自动显示滚动条。</p>
<h3 id="组合使用-overflow-x-和-overflow-y"><a href="#组合使用-overflow-x-和-overflow-y" class="headerlink" title="组合使用 overflow-x 和 overflow-y"></a>组合使用 <code>overflow-x</code> 和 <code>overflow-y</code></h3><p>有时你可能需要分别控制水平方向和垂直方向的溢出行为,这时可以使用 <code>overflow-x</code> 和 <code>overflow-y</code> 属性。</p>
<figure class="highlight css"><table><tr><td class="code"><pre><span class="line"><span class="selector-class">.container</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">200px</span>;</span><br><span class="line"> <span class="attribute">height</span>: <span class="number">100px</span>;</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> solid black;</span><br><span class="line"> <span class="attribute">overflow-x</span>: auto; <span class="comment">/* 水平方向自动显示滚动条 */</span></span><br><span class="line"> <span class="attribute">overflow-y</span>: hidden; <span class="comment">/* 垂直方向隐藏溢出内容 */</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
<h3 id="注意事项"><a href="#注意事项" class="headerlink" title="注意事项"></a>注意事项</h3><ul>
<li><code>overflow</code> 属性仅在元素具有限定的宽度和高度时起作用。</li>
<li><code>overflow</code> 属性常用于创建滚动区域,特别是在布局响应式设计中。</li>
</ul>
<p>通过合理使用 <code>overflow</code> 属性,可以更好地控制元素内容在水平方向和垂直方向上的显示方式,提升页面的可读性和用户体验。</p>
]]></content>
<tags>
<tag>CSS</tag>
</tags>
</entry>
<entry>
<title>Axios学习</title>
<url>/2024/05/24/Axios%E5%AD%A6%E4%B9%A0/</url>
<content><![CDATA[<h1 id="Axiso库"><a href="#Axiso库" class="headerlink" title="Axiso库"></a>Axiso库</h1><p><strong>官方介绍:</strong></p>
<p>Axios 是一个基于 <em><a href="https://javascript.info/promise-basics">promise</a></em> 网络请求库,作用于<a href="https://nodejs.org/"><code>node.js</code></a> 和浏览器中。 它是 <em><a href="https://www.lullabot.com/articles/what-is-an-isomorphic-application">isomorphic</a></em> 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js <code>http</code> 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。</p>
<p><strong>axios官方文档:</strong><a href="https://www.axios-http.cn/docs/intro">https://www.axios-http.cn/docs/intro</a></p>
<h2 id="更新"><a href="#更新" class="headerlink" title="更新"></a>更新</h2><p>2024.5.24 第一次更新,主要学习了一下Axiso的基本用法</p>
<h2 id="功能特点"><a href="#功能特点" class="headerlink" title="功能特点"></a>功能特点</h2><ul>
<li><p>在浏览器中发送XMLHttpRequest请求</p>
<blockquote>
<p>避免了兼容性问题,fech是存在兼容性问题的</p>
</blockquote>
</li>
<li><p>在node.js中发送http请求</p>
<blockquote>
<p>不需要关心在不同的环境用不同的API,axiso会自动识别环境,在不同的环境下用的都是同一个API</p>
</blockquote>
</li>
<li><p>支持 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promise</a> API</p>
</li>
<li><p>拦截请求和响应</p>
</li>
<li><p>转换请求和响应数据</p>
</li>
<li><p>取消请求</p>
</li>
<li><p>超时处理</p>
</li>
<li><p>查询参数序列化支持嵌套项处理</p>
</li>
<li><p>自动将请求体序列化为:</p>
<ul>
<li>JSON (<code>application/json</code>)</li>
<li>Multipart / FormData (<code>multipart/form-data</code>)</li>
<li>URL encoded form (<code>application/x-www-form-urlencoded</code>)</li>
</ul>
</li>
<li><p>将 HTML Form 转换成 JSON 进行请求</p>
</li>
<li><p>自动转换JSON数据</p>
</li>
<li><p>获取浏览器和 node.js 的请求进度,并提供额外的信息(速度、剩余时间)</p>
</li>
<li><p>为 node.js 设置带宽限制</p>
</li>
</ul>
<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><blockquote>
<p>npm install axios</p>
</blockquote>
<h2 id="在需要使用的js文件中引入axios"><a href="#在需要使用的js文件中引入axios" class="headerlink" title="在需要使用的js文件中引入axios"></a>在需要使用的js文件中引入axios</h2><blockquote>
<p>import axios from ‘axios’</p>
</blockquote>
<h2 id="axios请求方法"><a href="#axios请求方法" class="headerlink" title="axios请求方法"></a>axios请求方法</h2><h3 id="config请求配置"><a href="#config请求配置" class="headerlink" title="config请求配置"></a>config请求配置</h3><ul>
<li><p>url: <code>url</code> 是用于请求的服务器 URL</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">url</span>: <span class="string">'/user'</span>,</span><br></pre></td></tr></table></figure>
</li>
<li><p>method:<code>method</code> 是创建请求时使用的方法</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">method</span>: <span class="string">'get'</span>, <span class="comment">// 默认值</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>baseURL: <code>baseURL</code> 将自动加在 <code>url</code> 前面,除非 <code>url</code> 是一个绝对 URL。<br>它可以通过设置一个 <code>baseURL</code> 便于为 axios 实例的方法传递相对 URL</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// `baseURL` 将自动加在 `url` 前面,除非 `url` 是一个绝对 URL。</span></span><br><span class="line"> <span class="comment">// 它可以通过设置一个 `baseURL` 便于为 axios 实例的方法传递相对 URL</span></span><br><span class="line"> <span class="attr">baseURL</span>: <span class="string">'https://some-domain.com/api/'</span>,</span><br></pre></td></tr></table></figure>
</li>
<li><p>transformRequest: <code>transformRequest</code> 允许在向服务器发送前,修改请求数据。</p>
<ul>
<li>它只能用于 ‘PUT’, ‘POST’ 和 ‘PATCH’ 这几个请求方法。</li>
<li>数组中最后一个函数必须返回一个字符串, 一个Buffer实例,ArrayBuffer,FormData,或 Stream。</li>
<li>你可以修改请求头。</li>
</ul>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">transformRequest</span>: [<span class="keyword">function</span> (<span class="params">data, headers</span>) {</span><br><span class="line"> <span class="comment">// 对发送的 data 进行任意转换处理</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> data;</span><br><span class="line"> }],</span><br></pre></td></tr></table></figure>
</li>
<li><p>transformResponse:<code>transformResponse</code> 在传递给 then/catch 前,允许修改响应数据</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">transformResponse</span>: [<span class="keyword">function</span> (<span class="params">data</span>) {</span><br><span class="line"> <span class="comment">// 对接收的 data 进行任意转换处理</span></span><br><span class="line"> <span class="keyword">return</span> data;</span><br><span class="line"> }],</span><br></pre></td></tr></table></figure>
</li>
<li><p>自定义请求头</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">headers</span>: {<span class="string">'X-Requested-With'</span>: <span class="string">'XMLHttpRequest'</span>},</span><br></pre></td></tr></table></figure>
</li>
<li><p>params:<code>params</code> 是与请求一起发送的 URL 参数,必须是一个简单对象或 URLSearchParams 对象</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">params</span>: {</span><br><span class="line"> <span class="attr">ID</span>: <span class="number">12345</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure>
</li>
<li><p>paramsSerializer:<code>paramsSerializer</code>是可选方法,主要用于序列化<code>params</code></p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">paramsSerializer</span>: <span class="keyword">function</span> (<span class="params">params</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="title class_">Qs</span>.<span class="title function_">stringify</span>(params, {<span class="attr">arrayFormat</span>: <span class="string">'brackets'</span>})</span><br><span class="line"> },</span><br></pre></td></tr></table></figure>
</li>
<li><p>data:<code>data</code> 是作为请求体被发送的数据</p>
<ul>
<li>仅适用 ‘PUT’, ‘POST’, ‘DELETE 和 ‘PATCH’ 请求方法</li>
<li>在没有设置 <code>transformRequest</code> 时,则必须是以下类型之一:<ul>
<li>string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams</li>
<li>浏览器专属: FormData, File, Blob</li>
<li>Node 专属: Stream, Buffer</li>
</ul>
</li>
</ul>
</li>
</ul>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">data</span>: {</span><br><span class="line"> <span class="attr">firstName</span>: <span class="string">'Fred'</span></span><br><span class="line">},</span><br></pre></td></tr></table></figure>
<ul>
<li>timeout:<code>timeout</code> 指定请求超时的毫秒数。</li>
</ul>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 如果请求时间超过 `timeout` 的值,则请求会被中断</span></span><br><span class="line"><span class="attr">timeout</span>: <span class="number">1000</span>, <span class="comment">// 默认值是 `0` (永不超时)</span></span><br></pre></td></tr></table></figure>
<ul>
<li><p>withCredentials:<code>withCredentials</code> 表示跨域请求时是否需要使用凭证</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">withCredentials</span>: <span class="literal">false</span>, <span class="comment">// default</span></span><br></pre></td></tr></table></figure>
</li>
<li><p>adapter:<code>adapter</code> 允许自定义处理请求,这使测试更加容易。</p>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//返回一个 promise 并提供一个有效的响应</span></span><br><span class="line"><span class="attr">adapter</span>: <span class="keyword">function</span> (<span class="params">config</span>) {</span><br><span class="line"> <span class="comment">/* ... */</span></span><br><span class="line">},</span><br></pre></td></tr></table></figure>
</li>
<li><p>responseEncoding:<code>responseEncoding</code> 表示用于解码响应的编码 (Node.js 专属)</p>
<blockquote>
<p>注意:忽略 <code>responseType</code> 的值为 ‘stream’,或者是客户端请求</p>
</blockquote>
</li>
</ul>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="attr">responseEncoding</span>: <span class="string">'utf8'</span>, <span class="comment">// 默认值</span></span><br></pre></td></tr></table></figure>
<p>更多参数,查询:<a href="https://www.axios-http.cn/docs/req_config">https://www.axios-http.cn/docs/req_config</a></p>
<h3 id="axios"><a href="#axios" class="headerlink" title="axios"></a>axios</h3><p><code>axios(config)</code></p>
<h5 id="axios-config-——post请求"><a href="#axios-config-——post请求" class="headerlink" title="axios(config)——post请求"></a>axios(config)——<strong>post请求</strong></h5><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 发起一个post请求</span></span><br><span class="line"><span class="title function_">axios</span>({</span><br><span class="line"> <span class="attr">method</span>: <span class="string">'post'</span>,</span><br><span class="line"> <span class="attr">url</span>: <span class="string">'/user/12345'</span>,</span><br><span class="line"> <span class="attr">data</span>: {</span><br><span class="line"> <span class="attr">firstName</span>: <span class="string">'Fred'</span>,</span><br><span class="line"> <span class="attr">lastName</span>: <span class="string">'Flintstone'</span></span><br><span class="line"> }</span><br><span class="line">});</span><br></pre></td></tr></table></figure>
<h5 id="axios-config-——get请求"><a href="#axios-config-——get请求" class="headerlink" title="axios(config)——get请求"></a>axios(config)——<strong>get请求</strong></h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 在 node.js 用GET请求获取远程图片</span></span><br><span class="line"><span class="title function_">axios</span>({</span><br><span class="line"> <span class="attr">method</span>: <span class="string">'get'</span>,</span><br><span class="line"> <span class="attr">url</span>: <span class="string">'http://bit.ly/2mTM3nY'</span>,</span><br><span class="line"> <span class="attr">responseType</span>: <span class="string">'stream'</span></span><br><span class="line">})</span><br><span class="line"> .<span class="title function_">then</span>(<span class="keyword">function</span> (<span class="params">response</span>) {</span><br><span class="line"> response.<span class="property">data</span>.<span class="title function_">pipe</span>(fs.<span class="title function_">createWriteStream</span>(<span class="string">'ada_lovelace.jpg'</span>))</span><br><span class="line"> });</span><br></pre></td></tr></table></figure>
<h5 id="axios-url-config"><a href="#axios-url-config" class="headerlink" title="axios(url[, config])"></a>axios(url[, config])</h5><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">// 发起一个 GET 请求 (默认请求方式)</span></span><br><span class="line"><span class="title function_">axios</span>(<span class="string">'/user/12345'</span>);</span><br></pre></td></tr></table></figure>
<h3 id="请求别名"><a href="#请求别名" class="headerlink" title="请求别名"></a>请求别名</h3><h5 id="axios-request-config"><a href="#axios-request-config" class="headerlink" title="axios.request(config)"></a>axios.request(config)<a href="https://www.axios-http.cn/docs/api_intro#axiosrequestconfig"></a></h5><h5 id="axios-get-url-config"><a href="#axios-get-url-config" class="headerlink" title="axios.get(url[, config])"></a>axios.get(url[, config])<a href="https://www.axios-http.cn/docs/api_intro#axiosgeturl-config"></a></h5><h5 id="axios-delete-url-config"><a href="#axios-delete-url-config" class="headerlink" title="axios.delete(url[, config])"></a>axios.delete(url[, config])<a href="https://www.axios-http.cn/docs/api_intro#axiosdeleteurl-config"></a></h5><h5 id="axios-head-url-config"><a href="#axios-head-url-config" class="headerlink" title="axios.head(url[, config])"></a>axios.head(url[, config])<a href="https://www.axios-http.cn/docs/api_intro#axiosheadurl-config"></a></h5><h5 id="axios-options-url-config"><a href="#axios-options-url-config" class="headerlink" title="axios.options(url[, config])"></a>axios.options(url[, config])<a href="https://www.axios-http.cn/docs/api_intro#axiosoptionsurl-config"></a></h5><h5 id="axios-post-url-data-config"><a href="#axios-post-url-data-config" class="headerlink" title="axios.post(url[, data[, config]])"></a>axios.post(url[, data[, config]])<a href="https://www.axios-http.cn/docs/api_intro#axiosposturl-data-config"></a></h5><h5 id="axios-put-url-data-config"><a href="#axios-put-url-data-config" class="headerlink" title="axios.put(url[, data[, config]])"></a>axios.put(url[, data[, config]])<a href="https://www.axios-http.cn/docs/api_intro#axiosputurl-data-config"></a></h5><h5 id="axios-patch-url-data-config"><a href="#axios-patch-url-data-config" class="headerlink" title="axios.patch(url[, data[, config]])"></a>axios.patch(url[, data[, config]])<a href="https://www.axios-http.cn/docs/api_intro#axiospatchurl-data-config"></a></h5><h5 id="axios-postForm-url-data-config"><a href="#axios-postForm-url-data-config" class="headerlink" title="axios.postForm(url[, data[, config]])"></a>axios.postForm(url[, data[, config]])<a href="https://www.axios-http.cn/docs/api_intro#axiospostformurl-data-config"></a></h5><h5 id="axios-putForm-url-data-config"><a href="#axios-putForm-url-data-config" class="headerlink" title="axios.putForm(url[, data[, config]])"></a>axios.putForm(url[, data[, config]])<a href="https://www.axios-http.cn/docs/api_intro#axiosputformurl-data-config"></a></h5><h5 id="axios-patchForm-url-data-config"><a href="#axios-patchForm-url-data-config" class="headerlink" title="axios.patchForm(url[, data[, config]])"></a>axios.patchForm(url[, data[, config]])</h5><h3 id="常用的两个"><a href="#常用的两个" class="headerlink" title="常用的两个"></a>常用的两个</h3><h4 id="axios-get"><a href="#axios-get" class="headerlink" title="axios.get"></a>axios.get</h4><h4 id="axios-post"><a href="#axios-post" class="headerlink" title="axios.post"></a>axios.post</h4><p>Url:请求地址</p>
<p>data:请求体</p>
<p>config:配置</p>
<h3 id=""><a href="#" class="headerlink" title=""></a></h3>]]></content>
<tags>
<tag>Axios</tag>
</tags>
</entry>
<entry>
<title>vscode快捷键(mac中)</title>
<url>/2024/05/23/vscode%E5%BF%AB%E6%8D%B7%E9%94%AE/</url>
<content><![CDATA[<h1 id="vscode快捷键-mac中"><a href="#vscode快捷键-mac中" class="headerlink" title="vscode快捷键(mac中)"></a>vscode快捷键(mac中)</h1><h3 id="缩进"><a href="#缩进" class="headerlink" title="缩进"></a>缩进</h3><p>选中需要缩进的行,按住 <code>Command+]</code> 键。</p>
]]></content>
<tags>
<tag>实践</tag>
</tags>
</entry>
<entry>
<title>Vue-父子组件的通信</title>
<url>/2024/05/18/Vue-%E7%88%B6%E5%AD%90%E7%BB%84%E4%BB%B6%E7%9A%84%E9%80%9A%E4%BF%A1/</url>
<content><![CDATA[<h1 id="Vue-父子组件的通信"><a href="#Vue-父子组件的通信" class="headerlink" title="Vue-父子组件的通信"></a>Vue-父子组件的通信</h1><p>在 Vue.js 中,父子组件之间的通信可以通过 props 和 events 来实现。下面分别介绍了 props 和 events 的用法:</p>
<h3 id="使用-Props(父传子):"><a href="#使用-Props(父传子):" class="headerlink" title="使用 Props(父传子):"></a>使用 Props(父传子):</h3><ul>
<li>父组件可以通过 props 向子组件传递数据。</li>
<li>在子组件中,props 是响应式的,即当父组件的数据发生变化时,子组件会自动更新。</li>
<li>父组件通过在子组件上使用属性绑定的方式传递数据。</li>
</ul>
<p><strong>父组件:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><template></span><br><span class="line"> <ChildComponent :message="parentMessage" /></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><script></span><br><span class="line">import ChildComponent from './ChildComponent.vue';</span><br><span class="line"></span><br><span class="line">export default {</span><br><span class="line"> data() {</span><br><span class="line"> return {</span><br><span class="line"> parentMessage: 'Hello from Parent',</span><br><span class="line"> };</span><br><span class="line"> },</span><br><span class="line"> components: {</span><br><span class="line"> ChildComponent,</span><br><span class="line"> },</span><br><span class="line">};</span><br><span class="line"></script></span><br></pre></td></tr></table></figure>
<p><strong>子组件:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><template></span><br><span class="line"> <div>{{ message }}</div></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><script></span><br><span class="line">export default {</span><br><span class="line"> props: ['message'],</span><br><span class="line">};</span><br><span class="line"></script></span><br></pre></td></tr></table></figure>
<h3 id="使用-Events(子传父):"><a href="#使用-Events(子传父):" class="headerlink" title="使用 Events(子传父):"></a>使用 Events(子传父):</h3><ul>
<li>子组件可以通过 events 向父组件发送消息。</li>
<li>在子组件中使用 <code>$emit</code> 方法触发一个自定义事件,并传递数据。</li>
<li>父组件通过在子组件上监听自定义事件来接收子组件发送的消息。</li>
</ul>
<p><strong>父组件:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><template></span><br><span class="line"> <ChildComponent @child-event="handleChildEvent" /></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><script></span><br><span class="line">import ChildComponent from './ChildComponent.vue';</span><br><span class="line"></span><br><span class="line">export default {</span><br><span class="line"> methods: {</span><br><span class="line"> handleChildEvent(data) {</span><br><span class="line"> console.log('Received data from child:', data);</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line"> components: {</span><br><span class="line"> ChildComponent,</span><br><span class="line"> },</span><br><span class="line">};</span><br><span class="line"></script></span><br></pre></td></tr></table></figure>
<p><strong>子组件:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><template></span><br><span class="line"> <button @click="sendMessage">Send Message to Parent</button></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><script></span><br><span class="line">export default {</span><br><span class="line"> methods: {</span><br><span class="line"> sendMessage() {</span><br><span class="line"> this.$emit('child-event', 'Hello from Child');</span><br><span class="line"> },</span><br><span class="line"> },</span><br><span class="line">};</span><br><span class="line"></script></span><br></pre></td></tr></table></figure>
<p>通过 props 和 events,父子组件之间可以方便地进行通信,实现数据的传递和交互。</p>
]]></content>
</entry>
<entry>
<title>vue文档学习</title>
<url>/2024/05/18/vue%E6%96%87%E6%A1%A3%E5%AD%A6%E4%B9%A0/</url>
<content><![CDATA[<h1 id="Vue-js"><a href="#Vue-js" class="headerlink" title="Vue.js"></a>Vue.js</h1><p>vue官方文档 <a href="https://cn.vuejs.org/guide/introduction.html">https://cn.vuejs.org/guide/introduction.html</a></p>
<p>基于vue方法文档的学习笔记,初学时主要记录基础知识,深度学习后希望能加上自己的理解!</p>
<h3 id="更新时间"><a href="#更新时间" class="headerlink" title="更新时间"></a>更新时间</h3><p>2024.05.18第一次更新</p>
<h2 id="什么是Vue"><a href="#什么是Vue" class="headerlink" title="什么是Vue"></a>什么是Vue</h2><p>一款用于构建用户界面的 (JavaScript )渐进式框架框架</p>
<p>两个功能:</p>
<ul>
<li><strong>声明式渲染</strong>:vue的模板语法使得我们可以声明式地描述HTML和JS状态之间的关系</li>
<li><strong>响应性</strong>:自动跟踪JS状态并响应式地更新DOM</li>
</ul>
<h2 id="Vue可以使用的场景"><a href="#Vue可以使用的场景" class="headerlink" title="Vue可以使用的场景"></a>Vue可以使用的场景</h2><ul>
<li>无需构建步骤,渐进式增强静态的 HTML</li>
<li>在任何页面中作为 Web Components 嵌入</li>
<li>单页应用 (SPA)</li>
<li>全栈 / 服务端渲染 (SSR)</li>
<li>Jamstack / 静态站点生成 (SSG)</li>
<li>开发桌面端、移动端、WebGL,甚至是命令行终端中的界面</li>
</ul>
<h2 id="单文件组件(SFC——-vue"><a href="#单文件组件(SFC——-vue" class="headerlink" title="单文件组件(SFC——*.vue)"></a>单文件组件(SFC——*.vue)</h2><p>vue的标志性功能</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><script setup></span><br><span class="line"></script></span><br><span class="line"></span><br><span class="line"><template></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><style scoped scoped></span><br><span class="line"></style></span><br></pre></td></tr></table></figure>
<h2 id="Vue组件的书写风格"><a href="#Vue组件的书写风格" class="headerlink" title="Vue组件的书写风格"></a>Vue组件的书写风格</h2><h3 id="选项式API-(Option-API)"><a href="#选项式API-(Option-API)" class="headerlink" title="选项式API (Option API)"></a>选项式API (Option API)</h3><ul>
<li>用对象来描述组件逻辑</li>
<li>对象包括data、methos、mouted等属性,这些属性都是可选式的(我自己的理解,不一定对)</li>
<li>选项定义的属性会暴露在函数内部的this上(即可以通过this访问到这个属性),this指向当前组件的实例</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><script></span><br><span class="line">export default {</span><br><span class="line"> // data() 返回的属性将会成为响应式的状态</span><br><span class="line"> // 并且暴露在 `this` 上</span><br><span class="line"> data() {</span><br><span class="line"> return {</span><br><span class="line"> count: 0</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"></span><br><span class="line"> // methods 是一些用来更改状态与触发更新的函数</span><br><span class="line"> // 它们可以在模板中作为事件处理器绑定</span><br><span class="line"> methods: {</span><br><span class="line"> increment() {</span><br><span class="line"> this.count++</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"></span><br><span class="line"> // 生命周期钩子会在组件生命周期的各个不同阶段被调用</span><br><span class="line"> // 例如这个函数就会在组件挂载完成后被调用</span><br><span class="line"> mounted() {</span><br><span class="line"> console.log(`The initial count is ${this.count}.`)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></script></span><br><span class="line"></span><br><span class="line"><template></span><br><span class="line"> <button @click="increment">Count is: {{ count }}</button></span><br><span class="line"></template></span><br></pre></td></tr></table></figure>
<h3 id="组合式API(Composition-API)"><a href="#组合式API(Composition-API)" class="headerlink" title="组合式API(Composition API)"></a>组合式API(Composition API)</h3><ul>
<li>可以使用导入的API函数描述组件逻辑</li>
<li>组合式API与<code><script setup></code>搭配使用,其中<code>setup</code>是一个标识,使得我们可以更简洁地使用组合式API(会在编译时做一些处理)</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><script setup></span><br><span class="line">import { ref, onMounted } from 'vue'</span><br><span class="line"></span><br><span class="line">// 响应式状态</span><br><span class="line">const count = ref(0)</span><br><span class="line"></span><br><span class="line">// 用来修改状态、触发更新的函数</span><br><span class="line">function increment() {</span><br><span class="line"> count.value++</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">// 生命周期钩子</span><br><span class="line">onMounted(() => {</span><br><span class="line"> console.log(`The initial count is ${count.value}.`)</span><br><span class="line">})</span><br><span class="line"></script></span><br><span class="line"></span><br><span class="line"><template></span><br><span class="line"> <button @click="increment">Count is: {{ count }}</button></span><br><span class="line"></template></span><br></pre></td></tr></table></figure>
<h3 id="两者之间的异同"><a href="#两者之间的异同" class="headerlink" title="两者之间的异同"></a>两者之间的异同</h3><ul>
<li>选项式API基于组件式API</li>
<li>选项式有面对对象的思想,对初学者更友好,强制按照选项来组织代码</li>
<li>组件式的核心思想是直接在函数作用域内定义响应式状态变量,并从多个函数中得到的状态组合起来处理复杂问题。更自由、灵活,但更难理解(确实,我不太能理解)</li>
</ul>
<h2 id="互动教程(组件式API-SFC)"><a href="#互动教程(组件式API-SFC)" class="headerlink" title="互动教程(组件式API+SFC)"></a>互动教程(组件式API+SFC)</h2><h3 id="响应式变量声明方式"><a href="#响应式变量声明方式" class="headerlink" title="响应式变量声明方式"></a>响应式变量声明方式</h3><p>说的明白点,就是动态的数据绑定,在reactive或ref中声明的变量可以响应式地用在html中</p>
<h4 id="reactive-声明"><a href="#reactive-声明" class="headerlink" title="reactive()声明"></a>reactive()声明</h4><ul>
<li>reactive只适用于对象(包括数组和内置类型,如Map和Set)</li>
<li>reactive创建的对象时JS Proxy,行为与普通对象一致</li>
</ul>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> { reactive } <span class="keyword">from</span> <span class="string">'vue'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> counter = <span class="title function_">reactive</span>({</span><br><span class="line"> <span class="attr">count</span>: <span class="number">0</span></span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(counter.<span class="property">count</span>) <span class="comment">// 0</span></span><br><span class="line">counter.<span class="property">count</span>++</span><br></pre></td></tr></table></figure>
<h4 id="ref"><a href="#ref" class="headerlink" title="ref()"></a>ref()</h4><ul>
<li>ref接收任意类型数据</li>
<li>返回值是一个对象,可以通过对象.value属性访问数据</li>
</ul>
<figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="keyword">import</span> { ref } <span class="keyword">from</span> <span class="string">'vue'</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> message = <span class="title function_">ref</span>(<span class="string">'Hello World!'</span>)</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(message.<span class="property">value</span>) <span class="comment">// "Hello World!"</span></span><br><span class="line">message.<span class="property">value</span> = <span class="string">'Changed'</span></span><br></pre></td></tr></table></figure>
<h3 id="在模板template中使用响应式状态"><a href="#在模板template中使用响应式状态" class="headerlink" title="在模板template中使用响应式状态"></a>在模板template中使用响应式状态</h3><p>响应式状态暂时我喜欢理解为响应式变量</p>
<ul>
<li>使用<code>{{}}</code>使用,并且ref中的对象的value可以不用message.value去访问,而是可以使用message直接访问(因为会被自动解包)</li>
<li><code>{{}}</code>中不限制于变量名,也可以是表达式</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">//变量写法</span><br><span class="line"><h1>{{ message }}</h1></span><br><span class="line"><p>Count is: {{ counter.count }}</p></span><br><span class="line"></span><br><span class="line">//表达式写法</span><br><span class="line"><h1>{{ message.split('').reverse().join('') }}</h1></span><br></pre></td></tr></table></figure>
<h3 id="Attribute绑定(v-bind)"><a href="#Attribute绑定(v-bind)" class="headerlink" title="Attribute绑定(v-bind)"></a>Attribute绑定(v-bind)</h3><ul>
<li><p>Attribute n.属性,特质,在编程中通常用来描述数据对象的特征</p>
</li>
<li><p>v-bind用于绑定一个动态值,时v-开头的一种特殊Attribute</p>
</li>
<li><p>绑定的值可以是calss,可以是id,也可以是一些参数</p>
</li>
<li><p>可以简写为<code>:</code></p>
</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><div v-bind:id="dynamicId"></div></span><br><span class="line"></span><br><span class="line">//语法糖</span><br><span class="line"><div :id="dynamicId"></div></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<p>案例</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><script setup></span><br><span class="line">import { ref } from 'vue'</span><br><span class="line"></span><br><span class="line">const titleClass = ref('title')</span><br><span class="line"></script></span><br><span class="line"></span><br><span class="line"><template></span><br><span class="line"> <h1 :class="titleClass">Make me red</h1></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><style></span><br><span class="line">.title {</span><br><span class="line"> color: red;</span><br><span class="line">}</span><br><span class="line"></style></span><br></pre></td></tr></table></figure>
<h3 id="事件监听(v-on)"><a href="#事件监听(v-on)" class="headerlink" title="事件监听(v-on)"></a>事件监听(v-on)</h3><ul>
<li><p>使用v-on监听DOM事件</p>
</li>
<li><p>简写为@</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><template></span><br><span class="line"><button v-on:click="increment">{{ count }}</button></span><br><span class="line">//简写</span><br><span class="line"><button @click="increment">{{ count }}</button></span><br><span class="line"></span><br><span class="line"></template></span><br></pre></td></tr></table></figure>
</li>
<li><p>在script中声明回调函数increment</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><script setup></span><br><span class="line">import { ref } from 'vue'</span><br><span class="line"></span><br><span class="line">const count = ref(0)</span><br><span class="line"></span><br><span class="line">function increment() {</span><br><span class="line"> // 更新组件状态</span><br><span class="line"> count.value++</span><br><span class="line">}</span><br><span class="line"></script></span><br></pre></td></tr></table></figure></li>
</ul>
<h3 id="表单的双向绑定"><a href="#表单的双向绑定" class="headerlink" title="表单的双向绑定"></a>表单的双向绑定</h3><h4 id="使用v-bind-v-on"><a href="#使用v-bind-v-on" class="headerlink" title="使用v-bind+v-on"></a>使用v-bind+v-on</h4><p>当v-on监听到表单内容的变化,就使用回调函数获取到表单的新内容,更新数据后,重新响应在v-bind绑定的组件上</p>
<h4 id="使用v-model(常用于表单、单选、多选、下拉框)"><a href="#使用v-model(常用于表单、单选、多选、下拉框)" class="headerlink" title="使用v-model(常用于表单、单选、多选、下拉框)"></a>使用v-model(常用于表单、单选、多选、下拉框)</h4><ul>
<li>v-model是实质是上述方法的语法糖</li>
<li>V-model将绑定的值与input中的值自动同步,不需要在使用事件处理函数</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">//用法</span><br><span class="line"><input v-model="text"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//例子</span><br><span class="line"><script setup></span><br><span class="line">import { ref } from 'vue'</span><br><span class="line"></span><br><span class="line">const text = ref('')</span><br><span class="line"></span><br><span class="line"></script></span><br><span class="line"></span><br><span class="line"><template></span><br><span class="line"> <input v-model="text" placeholder="Type here"></span><br><span class="line"> <p>{{ text }}</p></span><br><span class="line"></template></span><br></pre></td></tr></table></figure>
<h3 id="条件渲染(v-if)"><a href="#条件渲染(v-if)" class="headerlink" title="条件渲染(v-if)"></a>条件渲染(v-if)</h3><ul>
<li><code>v-if</code>,只有在awesome为<code>true</code>时,<code>h1</code>标签才会被渲染</li>
<li><code>v-else-if</code>和<code>v-else</code>用法与JS中<code>if-else if-else</code>的用法基本一致</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">//v-if</span><br><span class="line"><h1 v-if="awesome">Vue is awesome!</h1></span><br><span class="line"></span><br><span class="line">//v-else</span><br><span class="line"><h1 v-if="awesome">Vue is awesome!</h1></span><br><span class="line"><h1 v-else>Oh no 😢</h1></span><br></pre></td></tr></table></figure>
<h3 id="列表渲染(v-for)"><a href="#列表渲染(v-for)" class="headerlink" title="列表渲染(v-for)"></a>列表渲染(v-for)</h3><ul>
<li><p>v-for用于循环渲染</p>
</li>
<li><p>给每个 todo 对象设置了唯一的 <code>id</code>,并且将它作为<a href="https://cn.vuejs.org/api/built-in-special-attributes.html#key">特殊的 <code>key</code> attribute</a> 绑定到每个 <code><li></code>。<code>key</code> 使得 Vue 能够精确的移动每个 <code><li></code>,以匹配对应的对象在数组中的位置。</p>
</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><ul></span><br><span class="line"> <li v-for="todo in todos" :key="todo.id"></span><br><span class="line"> {{ todo.text }}</span><br><span class="line"> </li></span><br><span class="line"></ul></span><br><span class="line"></span><br><span class="line">//在数组中新增数据</span><br><span class="line">todos.value.push(newTodo)</span><br><span class="line"></span><br><span class="line">//在数组中删除数据,过滤数据</span><br><span class="line">todos.value = todos.value.filter(/* ... */)</span><br></pre></td></tr></table></figure>
<p>案例</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><script setup></span><br><span class="line">import { ref } from 'vue'</span><br><span class="line"></span><br><span class="line">// 给每个 todo 对象一个唯一的 id</span><br><span class="line">let id = 0</span><br><span class="line"></span><br><span class="line">const newTodo = ref('')</span><br><span class="line">const todos = ref([</span><br><span class="line"> { id: id++, text: 'Learn HTML' },</span><br><span class="line"> { id: id++, text: 'Learn JavaScript' },</span><br><span class="line"> { id: id++, text: 'Learn Vue' }</span><br><span class="line">])</span><br><span class="line"></span><br><span class="line">function addTodo() {</span><br><span class="line"> // 新增todo</span><br><span class="line"> if(newTodo.value != ''){</span><br><span class="line"> console.log(newTodo.value);</span><br><span class="line"> todos.value.push({</span><br><span class="line"> id: id++,</span><br><span class="line"> text: newTodo.value</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> newTodo.value = ''//添加完数据后要重置为空</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">function removeTodo(todo) {</span><br><span class="line"> // 删除todo</span><br><span class="line"> todos.value = todos.value.filter((item)=>{</span><br><span class="line"> return item!=todo;</span><br><span class="line"> });</span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></script></span><br><span class="line"></span><br><span class="line"><template></span><br><span class="line"> <form @submit.prevent="addTodo"></span><br><span class="line"> <input v-model="newTodo" required placeholder="new todo"></span><br><span class="line"> <button>Add Todo</button></span><br><span class="line"> </form></span><br><span class="line"> <ul></span><br><span class="line"> <li v-for="todo in todos" :key="todo.id"></span><br><span class="line"> {{ todo.text }}</span><br><span class="line"> <button @click="removeTodo(todo)">X</button></span><br><span class="line"> </li></span><br><span class="line"> </ul></span><br><span class="line"></template></span><br></pre></td></tr></table></figure>
<h4 id="计算属性(computed)"><a href="#计算属性(computed)" class="headerlink" title="计算属性(computed)"></a>计算属性(computed)</h4><ul>
<li>创建一个计算属性 ref,这个 ref 会动态地根据其他响应式数据源来计算其 <code>.value</code></li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">import { ref, computed } from 'vue'</span><br><span class="line"></span><br><span class="line">const hideCompleted = ref(false)</span><br><span class="line">const todos = ref([</span><br><span class="line"> /* ... */</span><br><span class="line">])</span><br><span class="line"></span><br><span class="line">const filteredTodos = computed(() => {</span><br><span class="line"> // 根据 `todos.value` & `hideCompleted.value`</span><br><span class="line"> // 返回过滤后的 todo 项目</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">- <li v-for="todo in todos"></span><br><span class="line">+ <li v-for="todo in filteredTodos"></span><br></pre></td></tr></table></figure>
<p>案例</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><script setup></span><br><span class="line">import { ref, computed } from 'vue'</span><br><span class="line"></span><br><span class="line">let id = 0</span><br><span class="line"></span><br><span class="line">const newTodo = ref('')</span><br><span class="line">const hideCompleted = ref(false)</span><br><span class="line">const todos = ref([</span><br><span class="line"> { id: id++, text: 'Learn HTML', done: true },</span><br><span class="line"> { id: id++, text: 'Learn JavaScript', done: true },</span><br><span class="line"> { id: id++, text: 'Learn Vue', done: false }</span><br><span class="line">])</span><br><span class="line"></span><br><span class="line">//当hideCompleted为true的时候,应该隐藏掉todos中done属性为ture的属性,所以过滤时返回done为false的属性的对象</span><br><span class="line">const filteredTodos = computed(() => {</span><br><span class="line"> return hideCompleted.value</span><br><span class="line"> ? todos.value.filter((t) => !t.done)</span><br><span class="line"> : todos.value</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line">function addTodo() {</span><br><span class="line"> todos.value.push({ id: id++, text: newTodo.value, done: false })</span><br><span class="line"> newTodo.value = ''</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">function removeTodo(todo) {</span><br><span class="line"> todos.value = todos.value.filter((t) => t !== todo)</span><br><span class="line">}</span><br><span class="line"></script></span><br><span class="line"></span><br><span class="line"><template></span><br><span class="line"> <form @submit.prevent="addTodo"></span><br><span class="line"> <input v-model="newTodo" required placeholder="new todo"></span><br><span class="line"> <button>Add Todo</button></span><br><span class="line"> </form></span><br><span class="line"> <ul></span><br><span class="line"> <li v-for="todo in filteredTodos" :key="todo.id"></span><br><span class="line"> <input type="checkbox" v-model="todo.done"></span><br><span class="line"> <span :class="{ done: todo.done }">{{ todo.text }}</span></span><br><span class="line"> <button @click="removeTodo(todo)">X</button></span><br><span class="line"> </li></span><br><span class="line"> </ul></span><br><span class="line"> <button @click="hideCompleted = !hideCompleted"></span><br><span class="line"> {{ hideCompleted ? 'Show all' : 'Hide completed' }}</span><br><span class="line"> </button></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"><style></span><br><span class="line">.done {</span><br><span class="line"> text-decoration: line-through;</span><br><span class="line">}</span><br><span class="line"></style></span><br></pre></td></tr></table></figure>
<h3 id="生命周期和模板引用"><a href="#生命周期和模板引用" class="headerlink" title="生命周期和模板引用"></a>生命周期和模板引用</h3><ul>
<li>当我们需要手动操作DOM时,会需要使用<code>模板引用</code>,也就是指向模板中的一个DOM元素的ref</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line"><template></span><br><span class="line"><p ref="pElementRef">hello</p></span><br><span class="line"></template></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><script setup></span><br><span class="line">//使用同名ref访问该引用</span><br><span class="line">const pElementRef = ref(null)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">//要在挂载之后执行代码,我们可以使用 onMounted() 函数:</span><br><span class="line">import { onMounted } from 'vue'</span><br><span class="line"> //ref引用的是一个DOM元素,在这个例子中,就是一个p标签</span><br><span class="line">onMounted(() => {</span><br><span class="line"> // 此时组件已经挂载。</span><br><span class="line"> pElementRef.value.textContent = "你好"</span><br><span class="line">})</span><br><span class="line"></script></span><br></pre></td></tr></table></figure>
<p>此时,这个 ref 使用 null 值来初始化。这是因为当<script setup> 执行时,DOM 元素还不存在。模板引用 ref 只能在组件挂载后访问。</p>
<ul>
<li><code>onMounted</code>被称为<strong>生命周期钩子</strong>——它允许我们注册一个在组件的特定生命周期调用的回调函数。还有一些其他的钩子如 <code>onUpdated</code> 和 <code>onUnmounted</code>。</li>
</ul>
<h3 id="侦听器-watch"><a href="#侦听器-watch" class="headerlink" title="侦听器(watch)"></a>侦听器(watch)</h3><p>有时我们需要响应性地执行一些“副作用”——例如,当一个数字改变时将其输出到控制台。我们可以通过侦听器来实现它:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">import { ref, watch } from 'vue'</span><br><span class="line"></span><br><span class="line">const count = ref(0)</span><br><span class="line"></span><br><span class="line">watch(count, (newCount) => {</span><br><span class="line"> // 没错,console.log() 是一个副作用</span><br><span class="line"> console.log(`new count is: ${newCount}`)</span><br><span class="line">})</span><br></pre></td></tr></table></figure>
]]></content>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title>滑动窗口专项训练</title>
<url>/2024/05/16/%E6%BB%91%E5%8A%A8%E7%AA%97%E5%8F%A3%E4%B8%93%E9%A1%B9%E8%AE%AD%E7%BB%83/</url>
<content><![CDATA[<h1 id="滑动窗口专项训练"><a href="#滑动窗口专项训练" class="headerlink" title="滑动窗口专项训练"></a>滑动窗口专项训练</h1><h2 id="更新记录"><a href="#更新记录" class="headerlink" title="更新记录"></a>更新记录</h2><p>2024.5.17 第一次记录</p>
<h2 id="一般解题步骤"><a href="#一般解题步骤" class="headerlink" title="一般解题步骤"></a>一般解题步骤</h2><p>待更新</p>
<p>1.定义需要维护的变量</p>
<p>可能是:</p>
<ul>
<li>哈希表(map或set)</li>
<li>最短/最长长度</li>
</ul>
<p>2.初始化滑动窗口,<code>start</code>和<code>end</code>一般都初始化为0(如果是双指针两边夹的情况,一般都是贪心?)</p>
<ol start="3">
<li></li>
</ol>
<h2 id="解题模板"><a href="#解题模板" class="headerlink" title="解题模板"></a>解题模板</h2><p>由于自己的理解还不够深刻,这里借鉴大佬的思路</p>
<p><a href="https://leetcode.cn/problems/longest-substring-with-at-most-two-distinct-characters/solutions/879777/hua-dong-chuang-kou-zhen-di-jian-dan-yi-73bii">https://leetcode.cn/problems/longest-substring-with-at-most-two-distinct-characters/solutions/879777/hua-dong-chuang-kou-zhen-di-jian-dan-yi-73bii</a></p>
<p>大佬的是python的版本</p>
<figure class="highlight python"><table><tr><td class="code"><pre><span class="line"><span class="keyword">class</span> <span class="title class_">Solution</span>:</span><br><span class="line"> <span class="keyword">def</span> <span class="title function_">problemName</span>(<span class="params">self, s: <span class="built_in">str</span></span>) -> <span class="built_in">int</span>:</span><br><span class="line"> <span class="comment"># Step 1: 定义需要维护的变量们 (对于滑动窗口类题目,这些变量通常是最小长度,最大长度,或者哈希表)</span></span><br><span class="line"> x, y = ..., ...</span><br><span class="line"></span><br><span class="line"> <span class="comment"># Step 2: 定义窗口的首尾端 (start, end), 然后滑动窗口</span></span><br><span class="line"> start = <span class="number">0</span></span><br><span class="line"> <span class="keyword">for</span> end <span class="keyword">in</span> <span class="built_in">range</span>(<span class="built_in">len</span>(s)):</span><br><span class="line"> <span class="comment"># Step 3: 更新需要维护的变量, 有的变量需要一个if语句来维护 (比如最大最小长度)</span></span><br><span class="line"> x = new_x</span><br><span class="line"> <span class="keyword">if</span> condition:</span><br><span class="line"> y = new_y</span><br><span class="line"></span><br><span class="line"> <span class="string">'''</span></span><br><span class="line"><span class="string"> ------------- 下面是两种情况,读者请根据题意二选1 -------------</span></span><br><span class="line"><span class="string"> '''</span></span><br><span class="line"> <span class="comment"># Step 4 - 情况1</span></span><br><span class="line"> <span class="comment"># 如果题目的窗口长度固定:用一个if语句判断一下当前窗口长度是否超过限定长度 </span></span><br><span class="line"> <span class="comment"># 如果超过了,窗口左指针前移一个单位保证窗口长度固定, 在那之前, 先更新Step 1定义的(部分或所有)维护变量 </span></span><br><span class="line"> <span class="keyword">if</span> 窗口长度大于限定值:</span><br><span class="line"> <span class="comment"># 更新 (部分或所有) 维护变量 </span></span><br><span class="line"> <span class="comment"># 窗口左指针前移一个单位保证窗口长度固定</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># Step 4 - 情况2</span></span><br><span class="line"> <span class="comment"># 如果题目的窗口长度可变: 这个时候一般涉及到窗口是否合法的问题</span></span><br><span class="line"> <span class="comment"># 如果当前窗口不合法时, 用一个while去不断移动窗口左指针, 从而剔除非法元素直到窗口再次合法</span></span><br><span class="line"> <span class="comment"># 在左指针移动之前更新Step 1定义的(部分或所有)维护变量 </span></span><br><span class="line"> <span class="keyword">while</span> 不合法:</span><br><span class="line"> <span class="comment"># 更新 (部分或所有) 维护变量 </span></span><br><span class="line"> <span class="comment"># 不断移动窗口左指针直到窗口再次合法</span></span><br><span class="line"></span><br><span class="line"> <span class="comment"># Step 5: 返回答案</span></span><br><span class="line"> <span class="keyword">return</span> ...</span><br></pre></td></tr></table></figure>
<p>按照大佬是思路,改成JS的版本</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">string</span>} <span class="variable">s</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> problemName = <span class="keyword">function</span>(<span class="params">s</span>) {</span><br><span class="line"> <span class="comment">// Step 1: 定义需要维护的变量们 (对于滑动窗口类题目,这些变量通常是最小长度,最大长度,或者哈希表)</span></span><br><span class="line"> <span class="keyword">let</span> [x, y] = ...</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// Step 2: 定义窗口的首尾端 (start, end), 然后滑动窗口</span></span><br><span class="line"> <span class="keyword">let</span> st = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> end = <span class="number">0</span>; end < s.<span class="property">length</span>; s++){</span><br><span class="line"> <span class="comment">//Step 3: 更新需要维护的变量, 有的变量需要一个if语句来维护 (比如最大最小长度)</span></span><br><span class="line"> x = new_x;</span><br><span class="line"> <span class="keyword">if</span>(condition){</span><br><span class="line"> y = new_y;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// Step 4 - 情况1</span></span><br><span class="line"> <span class="comment">// 如果题目的窗口长度固定:用一个if语句判断一下当前窗口长度是否超过限定长度 </span></span><br><span class="line"> <span class="comment">// 如果超过了,窗口左指针前移一个单位保证窗口长度固定, 在那之前, 先更新Step 1定义的(部分或所有)维护变量 </span></span><br><span class="line"> <span class="keyword">if</span>(窗口长度大于限定值){</span><br><span class="line"> <span class="comment">// 更新 (部分或所有) 维护变量 </span></span><br><span class="line"> <span class="comment">// 窗口左指针前移一个单位保证窗口长度固定</span></span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// Step 4 - 情况2</span></span><br><span class="line"> <span class="comment">// 如果题目的窗口长度可变: 这个时候一般涉及到窗口是否合法的问题</span></span><br><span class="line"> <span class="comment">// 如果当前窗口不合法时, 用一个while去不断移动窗口左指针, 从而剔除非法元素直到窗口再次合法</span></span><br><span class="line"> <span class="comment">// 在左指针移动之前更新Step 1定义的(部分或所有)维护变量 </span></span><br><span class="line"> <span class="keyword">while</span>(不合法){</span><br><span class="line"> <span class="comment">//更新 (部分或所有) 维护变量 </span></span><br><span class="line"> <span class="comment">//不断移动窗口左指针直到窗口再次合法</span></span><br><span class="line"> } </span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// Step 5: 返回答案</span></span><br><span class="line"> <span class="keyword">return</span> ...</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h2 id="实战训练"><a href="#实战训练" class="headerlink" title="实战训练"></a>实战训练</h2><h3 id="无重复字符的最长子串"><a href="#无重复字符的最长子串" class="headerlink" title="无重复字符的最长子串"></a>无重复字符的最长子串</h3><p><a href="https://leetcode.cn/problems/longest-substring-without-repeating-characters/">3. 无重复字符的最长子串</a></p>
<p>给定一个字符串 <code>s</code> ,请你找出其中不含有重复字符的<strong>最长子串</strong>的长度。</p>
<p><strong>示例 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入: s = "abcabcbb"</span><br><span class="line">输出: 3 </span><br><span class="line">解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入: s = "bbbbb"</span><br><span class="line">输出: 1</span><br><span class="line">解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。</span><br></pre></td></tr></table></figure>
<p><strong>示例 3:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入: s = "pwwkew"</span><br><span class="line">输出: 3</span><br><span class="line">解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。</span><br><span class="line"> 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。</span><br></pre></td></tr></table></figure>
<p><strong>提示:</strong></p>
<ul>
<li><code>0 <= s.length <= 5 * 104</code></li>
<li><code>s</code> 由英文字母、数字、符号和空格组成</li>
</ul>
<p><strong>code:</strong></p>
<p>不用map,用set和单纯数组都行,数组的话就用include方法来查看字母是否已经存在于数组中,但是最好还是不要数组了,数组里面删除一个元素会很麻烦,主要还是哈希+滑动窗口的思想。</p>
<p>用set的话会简单一点点</p>
<p>带注释版本</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">string</span>} <span class="variable">s</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> lengthOfLongestSubstring = <span class="keyword">function</span>(<span class="params">s</span>) {</span><br><span class="line"> <span class="keyword">if</span>(s.<span class="property">length</span>==<span class="number">0</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="comment">//无重复字符的最长子串</span></span><br><span class="line"> <span class="comment">//ex</span></span><br><span class="line"> <span class="comment">// abcabcbb</span></span><br><span class="line"> <span class="comment">// abc -> maxLen = 3</span></span><br><span class="line"> <span class="comment">//滑动窗口</span></span><br><span class="line"> <span class="comment">//1.定义需要维护的变量</span></span><br><span class="line"> <span class="keyword">let</span> maxLen = -<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">let</span> hash = <span class="keyword">new</span> <span class="title class_">Map</span>();</span><br><span class="line"> <span class="comment">//2.定义窗口的首尾端,然后滑动窗口</span></span><br><span class="line"> <span class="keyword">let</span> st = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> end = <span class="number">0</span>; end < s.<span class="property">length</span>; end++){<span class="comment">//第一次debug是end++写成s++了</span></span><br><span class="line"> <span class="comment">//维护变量</span></span><br><span class="line"> <span class="keyword">let</span> c = s[end];</span><br><span class="line"> </span><br><span class="line"> <span class="comment">//情况2:窗口可变,检查窗口是否合法,不合法就调整st指针直至合法 </span></span><br><span class="line"> <span class="comment">//在该题目中,不合法指的是,字符串中出现重复字符 </span></span><br><span class="line"> <span class="keyword">if</span>(hash.<span class="title function_">has</span>(c)){<span class="comment">//c字符不是第一次出现,窗口不合法</span></span><br><span class="line"> <span class="comment">//只要连续移动字符,直到新的窗口的字符中不包含第一次出现的c字符位置</span></span><br><span class="line"> <span class="keyword">while</span>( st < end && s[st] != c){</span><br><span class="line"> hash.<span class="title function_">delete</span>(s[st]);<span class="comment">//第二次debug,这一句和下面一句的顺序反了,如果先++在delet,那么相当于delet的是下一个字符,第一个字符永远都不会被移除</span></span><br><span class="line"> st++;</span><br><span class="line"> } </span><br><span class="line"> <span class="comment">//此时的st应该位于第一个窗口的第一个c字符处</span></span><br><span class="line"> st++;</span><br><span class="line"> <span class="comment">//现在窗口合法了</span></span><br><span class="line"> }<span class="keyword">else</span>{<span class="comment">//第一次出现</span></span><br><span class="line"> hash.<span class="title function_">set</span>(c, <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//窗口的长度为end - st + 1 (左闭右闭区间)</span></span><br><span class="line"> <span class="comment">//如果是左闭右开区间,就是end - st</span></span><br><span class="line"> maxLen = <span class="title class_">Math</span>.<span class="title function_">max</span>(maxLen, end - st + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> maxLen;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>不带注释</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">string</span>} <span class="variable">s</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> lengthOfLongestSubstring = <span class="keyword">function</span>(<span class="params">s</span>) {</span><br><span class="line"> <span class="keyword">if</span>(s.<span class="property">length</span>==<span class="number">0</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">let</span> maxLen = -<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">let</span> hash = <span class="keyword">new</span> <span class="title class_">Map</span>();</span><br><span class="line"> <span class="keyword">let</span> st = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> end = <span class="number">0</span>; end < s.<span class="property">length</span>; end++){</span><br><span class="line"> <span class="keyword">let</span> c = s[end]; </span><br><span class="line"> <span class="keyword">if</span>(hash.<span class="title function_">has</span>(c)){</span><br><span class="line"> <span class="keyword">while</span>( st < end && s[st] != c){</span><br><span class="line"> hash.<span class="title function_">delete</span>(s[st]);</span><br><span class="line"> st++;</span><br><span class="line"> } </span><br><span class="line"> st++;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> hash.<span class="title function_">set</span>(c, <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> maxLen = <span class="title class_">Math</span>.<span class="title function_">max</span>(maxLen, end - st + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> maxLen;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h3 id="找到字符串中所有字母异位词"><a href="#找到字符串中所有字母异位词" class="headerlink" title="找到字符串中所有字母异位词"></a>找到字符串中所有字母异位词</h3><p><a href="https://leetcode.cn/problems/find-all-anagrams-in-a-string/">438. 找到字符串中所有字母异位词</a></p>
<p>给定两个字符串 <code>s</code> 和 <code>p</code>,找到 <code>s</code> 中所有 <code>p</code> 的 <strong>异位词</strong> 的子串,返回这些子串的起始索引。不考虑答案输出的顺序。</p>
<p><strong>异位词</strong> 指由相同字母重排列形成的字符串(包括相同的字符串)。</p>
<p><strong>示例 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入: s = "cbaebabacd", p = "abc"</span><br><span class="line">输出: [0,6]</span><br><span class="line">解释:</span><br><span class="line">起始索引等于 0 的子串是 "cba", 它是 "abc" 的异位词。</span><br><span class="line">起始索引等于 6 的子串是 "bac", 它是 "abc" 的异位词。</span><br></pre></td></tr></table></figure>
<p> <strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入: s = "abab", p = "ab"</span><br><span class="line">输出: [0,1,2]</span><br><span class="line">解释:</span><br><span class="line">起始索引等于 0 的子串是 "ab", 它是 "ab" 的异位词。</span><br><span class="line">起始索引等于 1 的子串是 "ba", 它是 "ab" 的异位词。</span><br><span class="line">起始索引等于 2 的子串是 "ab", 它是 "ab" 的异位词。</span><br></pre></td></tr></table></figure>
<p><strong>Code:</strong></p>
<p>窗口不合理的情况比较复杂</p>
<p>带注释版本</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">string</span>} <span class="variable">s</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">string</span>} <span class="variable">p</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number[]</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> findAnagrams = <span class="keyword">function</span>(<span class="params">s, p</span>) {</span><br><span class="line"> <span class="comment">//哈希(异位词)+滑动窗口(子串)</span></span><br><span class="line"> <span class="comment">//异位词的特点是:</span></span><br><span class="line"> <span class="comment">//1.长度相等</span></span><br><span class="line"> <span class="comment">//2.每个字符的出现次数相等</span></span><br><span class="line"> <span class="keyword">let</span> hash = <span class="keyword">new</span> <span class="title class_">Map</span>();</span><br><span class="line"> <span class="keyword">let</span> hash2 = <span class="keyword">new</span> <span class="title class_">Map</span>();</span><br><span class="line"> <span class="keyword">let</span> res = [];</span><br><span class="line"> <span class="comment">//初始化hash</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i < p.<span class="property">length</span>; i++){</span><br><span class="line"> <span class="keyword">if</span>(hash.<span class="title function_">has</span>(p[i])){</span><br><span class="line"> hash.<span class="title function_">set</span>(p[i], hash.<span class="title function_">get</span>(p[i]) + <span class="number">1</span>);</span><br><span class="line"> }<span class="keyword">else</span> hash.<span class="title function_">set</span>(p[i], <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//初始化窗口,并开始滑动</span></span><br><span class="line"> <span class="keyword">let</span> st = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> end = <span class="number">0</span>; end < s.<span class="property">length</span>; end++){</span><br><span class="line"> <span class="keyword">let</span> c = s[end];</span><br><span class="line"> <span class="keyword">if</span>(hash2.<span class="title function_">has</span>(c)){</span><br><span class="line"> hash2.<span class="title function_">set</span>(c, hash2.<span class="title function_">get</span>(c) + <span class="number">1</span>);</span><br><span class="line"> }<span class="keyword">else</span> hash2.<span class="title function_">set</span>(c, <span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//窗口不合法1,没有这个字符,两个指针都跳到这个指针后面</span></span><br><span class="line"> <span class="keyword">if</span>(!hash.<span class="title function_">has</span>(c)){</span><br><span class="line"> <span class="keyword">while</span>(st != end + <span class="number">1</span>){<span class="comment">//debug1,一开始没有跳转到st = end+1,只是st++,这样是不对的,而且跳转完之后,一定要记得移除hash2中前面的(已经不在滑动窗口中的)字母</span></span><br><span class="line"> hash2.<span class="title function_">set</span>(s[st], hash2.<span class="title function_">get</span>(s[st]) - <span class="number">1</span>);</span><br><span class="line"> st++;</span><br><span class="line"> }</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(hash2.<span class="title function_">get</span>(c) > hash.<span class="title function_">get</span>(c)){</span><br><span class="line"> <span class="comment">//窗口不合法2,有这个字符,但是字符数多了,移动st,直到窗口中的c的字符数与hash中的字符数一致</span></span><br><span class="line"> <span class="keyword">while</span>(hash2.<span class="title function_">get</span>(c) != hash.<span class="title function_">get</span>(c)){</span><br><span class="line"> hash2.<span class="title function_">set</span>(s[st], hash2.<span class="title function_">get</span>(s[st]) - <span class="number">1</span>);</span><br><span class="line"> st++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//窗口不合法3,窗口长度超过了</span></span><br><span class="line"> <span class="keyword">while</span>(end - st + <span class="number">1</span> > p.<span class="property">length</span>){</span><br><span class="line"> hash2.<span class="title function_">set</span>(s[st], hash2.<span class="title function_">get</span>(s[st]) - <span class="number">1</span>);<span class="comment">//debug2,滑动了窗口,但是忘记处理hash2了</span></span><br><span class="line"> st++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(end - st + <span class="number">1</span> === p.<span class="property">length</span>){</span><br><span class="line"> res.<span class="title function_">push</span>(st);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>不带注释版本</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">string</span>} <span class="variable">s</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">string</span>} <span class="variable">p</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number[]</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> findAnagrams = <span class="keyword">function</span>(<span class="params">s, p</span>) {</span><br><span class="line"> <span class="keyword">let</span> hash = <span class="keyword">new</span> <span class="title class_">Map</span>();</span><br><span class="line"> <span class="keyword">let</span> hash2 = <span class="keyword">new</span> <span class="title class_">Map</span>();</span><br><span class="line"> <span class="keyword">let</span> res = [];</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i < p.<span class="property">length</span>; i++){</span><br><span class="line"> <span class="keyword">if</span>(hash.<span class="title function_">has</span>(p[i])){</span><br><span class="line"> hash.<span class="title function_">set</span>(p[i], hash.<span class="title function_">get</span>(p[i]) + <span class="number">1</span>);</span><br><span class="line"> }<span class="keyword">else</span> hash.<span class="title function_">set</span>(p[i], <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">let</span> st = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> end = <span class="number">0</span>; end < s.<span class="property">length</span>; end++){</span><br><span class="line"> <span class="keyword">let</span> c = s[end];</span><br><span class="line"> <span class="keyword">if</span>(hash2.<span class="title function_">has</span>(c)){</span><br><span class="line"> hash2.<span class="title function_">set</span>(c, hash2.<span class="title function_">get</span>(c) + <span class="number">1</span>);</span><br><span class="line"> }<span class="keyword">else</span> hash2.<span class="title function_">set</span>(c, <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span>(!hash.<span class="title function_">has</span>(c)){</span><br><span class="line"> <span class="keyword">while</span>(st != end + <span class="number">1</span>){</span><br><span class="line"> hash2.<span class="title function_">set</span>(s[st], hash2.<span class="title function_">get</span>(s[st]) - <span class="number">1</span>);</span><br><span class="line"> st++;</span><br><span class="line"> }</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(hash2.<span class="title function_">get</span>(c) > hash.<span class="title function_">get</span>(c)){</span><br><span class="line"> <span class="keyword">while</span>(hash2.<span class="title function_">get</span>(c) != hash.<span class="title function_">get</span>(c)){</span><br><span class="line"> hash2.<span class="title function_">set</span>(s[st], hash2.<span class="title function_">get</span>(s[st]) - <span class="number">1</span>);</span><br><span class="line"> st++;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span>(end - st + <span class="number">1</span> > p.<span class="property">length</span>){</span><br><span class="line"> hash2.<span class="title function_">set</span>(s[st], hash2.<span class="title function_">get</span>(s[st]) - <span class="number">1</span>);</span><br><span class="line"> st++;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(end - st + <span class="number">1</span> === p.<span class="property">length</span>){</span><br><span class="line"> res.<span class="title function_">push</span>(st);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
]]></content>
<tags>
<tag>算法</tag>
<tag>动态规划</tag>
</tags>
</entry>
<entry>
<title>动态规划专项训练</title>
<url>/2024/05/13/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E4%B8%93%E9%A1%B9%E8%AE%AD%E7%BB%83/</url>
<content><![CDATA[<h1 id="动态规划专项训练"><a href="#动态规划专项训练" class="headerlink" title="动态规划专项训练"></a>动态规划专项训练</h1><p>参考:代码随想录官⽹<a href="http://www.programmercarl.com/">www.programmercarl.com</a></p>
<h2 id="更新记录"><a href="#更新记录" class="headerlink" title="更新记录"></a>更新记录</h2><p>第一次更新 2024.05.13</p>
<p>第二次更新 2024.05.17</p>
<h2 id="一般解题步骤"><a href="#一般解题步骤" class="headerlink" title="一般解题步骤"></a>一般解题步骤</h2><ol>
<li>确定dp数组(dp table)以及下标的含义</li>
</ol>
<p> dp数组(状态转移数组)可以是一维的可以是二维的</p>
<ol start="2">
<li>确定递推公式 (状态转移方程)</li>
<li>dp数组如何初始化</li>
<li>确定遍历顺序</li>
<li>举例推导dp数组</li>
</ol>
<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><p><a href="https://leetcode.cn/problems/fibonacci-number/">509. 斐波那契数</a></p>
<p><strong>斐波那契数</strong> (通常用 <code>F(n)</code> 表示)形成的序列称为 <strong>斐波那契数列</strong> 。该数列由 <code>0</code> 和 <code>1</code> 开始,后面的每一项数字都是前面两项数字的和。也就是:</p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">F(0) = 0,F(1) = 1</span><br><span class="line">F(n) = F(n - 1) + F(n - 2),其中 n > 1</span><br></pre></td></tr></table></figure>
<p>给定 <code>n</code> ,请计算 <code>F(n)</code> 。</p>
<p><strong>示例 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:n = 2</span><br><span class="line">输出:1</span><br><span class="line">解释:F(2) = F(1) + F(0) = 1 + 0 = 1</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:n = 3</span><br><span class="line">输出:2</span><br><span class="line">解释:F(3) = F(2) + F(1) = 1 + 1 = 2</span><br></pre></td></tr></table></figure>
<p><strong>示例 3:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:n = 4</span><br><span class="line">输出:3</span><br><span class="line">解释:F(4) = F(3) + F(2) = 2 + 1 = 3</span><br></pre></td></tr></table></figure>
<p><strong>提示:</strong></p>
<ul>
<li><code>0 <= n <= 30</code></li>
</ul>
<p><strong>code:</strong></p>
<p>用模拟的思想做的,非dp</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">n</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> fib = <span class="keyword">function</span>(<span class="params">n</span>) {</span><br><span class="line"> <span class="keyword">if</span>(n === <span class="number">0</span>) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">if</span>(n === <span class="number">1</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">let</span> num1 = <span class="number">0</span>, num2 = <span class="number">1</span>;</span><br><span class="line"> <span class="keyword">let</span> cur;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">2</span>; i <= n; i++){</span><br><span class="line"> cur = num1 + num2;</span><br><span class="line"> num1 = num2;</span><br><span class="line"> num2 = cur;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> cur; </span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p><strong>用动态规划来做</strong></p>
<ol>
<li><p>确定dp数组(dp table)以及下标的含义 </p>
<p>dp[i]表示第i个斐波那契数</p>
</li>
<li><p>确定递推公式</p>
<p>题目 中有 dp[i] = dp[i - 1] + dp[i - 2]</p>
</li>
<li><p>dp数组如何初始化</p>
<p>题目中有 dp[0] = 0 , dp[1] = 1</p>
</li>
<li><p>确定遍历顺序</p>
<p>是从后向前还是从前向后,是一层还是两层,如果是两层,哪层在外面</p>
</li>
<li><p>打印推导dp数组(debug用的)</p>
</li>
</ol>
<h4 id="70-爬楼梯"><a href="#70-爬楼梯" class="headerlink" title="70. 爬楼梯"></a>70. 爬楼梯</h4><p><a href="https://leetcode.cn/problems/climbing-stairs/">70. 爬楼梯</a></p>
<p>假设你正在爬楼梯。需要 <code>n</code> 阶你才能到达楼顶。</p>
<p>每次你可以爬 <code>1</code> 或 <code>2</code> 个台阶。你有多少种不同的方法可以爬到楼顶呢?</p>
<p><strong>示例 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:n = 2</span><br><span class="line">输出:2</span><br><span class="line">解释:有两种方法可以爬到楼顶。</span><br><span class="line">1. 1 阶 + 1 阶</span><br><span class="line">2. 2 阶</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:n = 3</span><br><span class="line">输出:3</span><br><span class="line">解释:有三种方法可以爬到楼顶。</span><br><span class="line">1. 1 阶 + 1 阶 + 1 阶</span><br><span class="line">2. 1 阶 + 2 阶</span><br><span class="line">3. 2 阶 + 1 阶</span><br></pre></td></tr></table></figure>
<p><strong>提示:</strong></p>
<ul>
<li><code>1 <= n <= 45</code></li>
</ul>
<p><strong>code:</strong></p>
<p>在前面知识的基础上,我大概能了解到迈上第n阶的方法其实是有前面的迈上n-1和迈上n-2阶的种数有关的,但是如果没有关键点的想,很容易想岔去。</p>
<p>下面的代码是我第一个自己思考的代码,是错误的,一开始想的是想的是比如想要到第4阶,有可能是dp[1] + dp[3], dp[2]+ dp[2], dp[3] + dp[1];但是如果这样想的话,所有种类中是会有重复值的。所以我也想到了要去重,但是去重的规律并没有找对;</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">n</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> climbStairs = <span class="keyword">function</span>(<span class="params">n</span>) {</span><br><span class="line"> <span class="comment">//dp[i]表示爬到i阶楼梯,有dp[i]种方法</span></span><br><span class="line"> <span class="keyword">let</span> dp = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>];</span><br><span class="line"> <span class="comment">//初始化dp[]</span></span><br><span class="line"> <span class="comment">//状态转移方程</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">3</span>; i <= n; i++){</span><br><span class="line"> <span class="keyword">let</span> cn = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> k = <span class="number">1</span>; k < i; k++){</span><br><span class="line"> cn += (dp[k] * dp[i - k]);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//去除重复值</span></span><br><span class="line"> cn = cn - <span class="number">2</span> * i + <span class="number">5</span>;</span><br><span class="line"> dp.<span class="title function_">push</span>(cn);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[n];</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>看了卡哥的视频解说,反复想了一下理解了,其实思路是可以有很多种的,但是如果想用动态规划的思路来写,关键点在于<code>状态转移</code>,如果从0阶开始向上迈,那么状态转移方程其实很不好把握,容易像我之前一样想岔了,会想:先走几阶有几种方法,后走几阶有几种方法,很容易把自己绕进去。</p>
<p>但是如果想要专注于状态转移,应该<strong>从台阶上往下看</strong>,而且必须注意状态转移的条件(即每次只能爬1或2个台阶),那么对于一个人来说,他走到n层台阶的上一个状态只可能有两种:</p>
<ol>
<li>上一个状态是走到了n-1个台阶,他是迈了一步才走到n台阶的</li>
<li>上一个状态是走到了n-2个台阶,他是迈了两步才走到n台阶的</li>
</ol>
<p>可以想到,这样递归出来的种类数其实是很干净的,不会存在重复值,因为不同于我第一次的想法,我第一次想的是(**step1:**从0-k有几种方法; **step2:**从k-n有几种方法),而动态规划中,强制了我的step2只能有一种方法。举个例子:</p>
<p>易得dp[1] = 1, dp[2]= 2</p>
<p>如果我想求dp[4]</p>
<p>先看看我原本的想法:可能性有先走一步,再走三步;先走二步,再走两步;先走三步,再走一步</p>
<p>那么这个<code>dp[4]=dp[1]*dp[3]+ dp[2]*dp[2]+dp[3]*dp[1]</code>,但是这样的递归推导是不干净的,因为里面存在了很多的重复值</p>
<p>再看看动态规划的思想:如果我想根据step1+step2的思路来思考的话,首先强制step2的方法只能有一种,即当走过step1方法到达中间的某个台阶后,我只能通过一种方法来到达台阶n。</p>
<p>虽然step只能有一种方法,但是step可以有两种情况:即先走 2步,然后走2步到n;或者先走3步,然后走1步到n;</p>
<p>由此可得到:dp[4] = d[2] * 1 + d[3] * 1;</p>
<p>所以我才得出了dp的关键在于:到达这个状态的上一个状态是怎么样的,因为上一个状态总是通过一次操作(一次状态转移)达到这个状态,这样递归下来的数据才是干净的。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">n</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> climbStairs = <span class="keyword">function</span>(<span class="params">n</span>) {</span><br><span class="line"> <span class="comment">//dp[i]表示爬到i阶楼梯,有dp[i]种方法</span></span><br><span class="line"> <span class="keyword">let</span> dp = [<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>];</span><br><span class="line"> <span class="comment">//状态转移方程</span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">3</span>; i <= n; i++){</span><br><span class="line"> dp.<span class="title function_">push</span>(dp[i - <span class="number">1</span>] + dp[i - <span class="number">2</span>]);<span class="comment">//可以不用维护数组,直接用变量来写,写法上一题斐波那契数写法一致,不写了这里</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[n];</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h4 id="使用最小花费爬楼梯"><a href="#使用最小花费爬楼梯" class="headerlink" title="使用最小花费爬楼梯"></a>使用最小花费爬楼梯</h4><p><a href="https://leetcode.cn/problems/min-cost-climbing-stairs/">746. 使用最小花费爬楼梯</a></p>
<p>给你一个整数数组 <code>cost</code> ,其中 <code>cost[i]</code> 是从楼梯第 <code>i</code> 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。</p>
<p>你可以选择从下标为 <code>0</code> 或下标为 <code>1</code> 的台阶开始爬楼梯。</p>
<p>请你计算并返回达到楼梯顶部的最低花费。</p>
<p><strong>示例 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:cost = [10,15,20]</span><br><span class="line">输出:15</span><br><span class="line">解释:你将从下标为 1 的台阶开始。</span><br><span class="line">- 支付 15 ,向上爬两个台阶,到达楼梯顶部。</span><br><span class="line">总花费为 15 。</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:cost = [1,100,1,1,1,100,1,1,100,1]</span><br><span class="line">输出:6</span><br><span class="line">解释:你将从下标为 0 的台阶开始。</span><br><span class="line">- 支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。</span><br><span class="line">- 支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。</span><br><span class="line">- 支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。</span><br><span class="line">- 支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。</span><br><span class="line">- 支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。</span><br><span class="line">- 支付 1 ,向上爬一个台阶,到达楼梯顶部。</span><br><span class="line">总花费为 6 。</span><br></pre></td></tr></table></figure>
<p><strong>提示:</strong></p>
<ul>
<li><code>2 <= cost.length <= 1000</code></li>
<li><code>0 <= cost[i] <= 999</code></li>
</ul>
<p><strong>Code:</strong></p>
<p>这道题的难点在于搞清楚<code>ct[i]</code>到底指的是什么?</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number[]</span>} <span class="variable">cost</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//ct[i]指的是到达i(此时i是楼顶)的最小消费</span></span><br><span class="line"><span class="keyword">var</span> minCostClimbingStairs = <span class="keyword">function</span>(<span class="params">cost</span>) {</span><br><span class="line"> <span class="comment">//ct[i]达到i台阶的需要最小消费</span></span><br><span class="line"> <span class="keyword">if</span>(cost.<span class="property">length</span>==<span class="number">1</span>) <span class="keyword">return</span> cost[<span class="number">0</span>];</span><br><span class="line"> <span class="keyword">if</span>(cost.<span class="property">length</span>==<span class="number">2</span>) <span class="keyword">return</span> <span class="title class_">Math</span>.<span class="title function_">min</span>(cost[<span class="number">0</span>],cost[<span class="number">1</span>]);</span><br><span class="line"> <span class="keyword">let</span> ct1 = <span class="title class_">Math</span>.<span class="title function_">min</span>(cost[<span class="number">0</span>],cost[<span class="number">1</span>]);</span><br><span class="line"> <span class="keyword">let</span> ct = [<span class="number">0</span>, <span class="number">0</span>];</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">2</span>; i <= cost.<span class="property">length</span>; i++){</span><br><span class="line"> <span class="keyword">let</span> cur = <span class="title class_">Math</span>.<span class="title function_">min</span>(ct[i - <span class="number">1</span>]+cost[i - <span class="number">1</span>], ct[i-<span class="number">2</span>]+cost[i-<span class="number">2</span>]);</span><br><span class="line"> ct.<span class="title function_">push</span>(cur);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> ct[ct.<span class="property">length</span> - <span class="number">1</span>];</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h4 id="不同路径【Mid】"><a href="#不同路径【Mid】" class="headerlink" title="不同路径【Mid】"></a>不同路径【Mid】</h4><p><a href="https://leetcode.cn/problems/unique-paths/">62. 不同路径</a></p>
<p>一个机器人位于一个 <code>m x n</code> 网格的左上角 (起始点在下图中标记为 “Start” )。</p>
<p>机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。</p>
<p>问总共有多少条不同的路径?</p>
<p><strong>示例 1:</strong></p>
<p><img src="https://pic.leetcode.cn/1697422740-adxmsI-image.png" alt="img"></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:m = 3, n = 7</span><br><span class="line">输出:28</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:m = 3, n = 2</span><br><span class="line">输出:3</span><br><span class="line">解释:</span><br><span class="line">从左上角开始,总共有 3 条路径可以到达右下角。</span><br><span class="line">1. 向右 -> 向下 -> 向下</span><br><span class="line">2. 向下 -> 向下 -> 向右</span><br><span class="line">3. 向下 -> 向右 -> 向下</span><br></pre></td></tr></table></figure>
<p><strong>示例 3:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:m = 7, n = 3</span><br><span class="line">输出:28</span><br></pre></td></tr></table></figure>
<p><strong>示例 4:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:m = 3, n = 3</span><br><span class="line">输出:6</span><br></pre></td></tr></table></figure>
<h5 id="用dp来写"><a href="#用dp来写" class="headerlink" title="用dp来写"></a>用dp来写</h5><h4 id="code"><a href="#code" class="headerlink" title="code"></a>code</h4><p>d[x][y]表示从start开始到点(x,y)有d[x][y]种走法</p>
<p>关键点在于只能向下走或者向右走,所以x和y都智能递增,是不可能回头的,所以对于边缘d[x][1]和d[1][y]都应该初始化为1;</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">m</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">n</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> uniquePaths = <span class="keyword">function</span>(<span class="params">m, n</span>) {</span><br><span class="line"> <span class="comment">//初始化d[x][y]边缘元素为1</span></span><br><span class="line"> <span class="keyword">let</span> d = <span class="keyword">new</span> <span class="title class_">Array</span>(m + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> x = <span class="number">1</span>; x <= m; x++){</span><br><span class="line"> d[x] = <span class="keyword">new</span> <span class="title class_">Array</span>(n + <span class="number">1</span>);</span><br><span class="line"> <span class="keyword">if</span>(x == <span class="number">1</span>) d[<span class="number">1</span>].<span class="title function_">fill</span>(<span class="number">1</span>);</span><br><span class="line"> d[x][<span class="number">1</span>] = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> x = <span class="number">2</span>; x <= m; x++){</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> y = <span class="number">2</span>; y <= n; y++){</span><br><span class="line"> d[x][y] = d[x][y - <span class="number">1</span>] + d[x - <span class="number">1</span>][y];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(d);</span><br><span class="line"> <span class="keyword">return</span> d[m][n];</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h5 id="DFS的基本写法"><a href="#DFS的基本写法" class="headerlink" title="DFS的基本写法"></a>DFS的基本写法</h5><p>在JavaScript中,深度优先搜索(DFS)的一般写法与其他编程语言类似。下面是一个基本的DFS函数示例,用于在一个图或树结构中进行深度优先搜索:</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="keyword">function</span> <span class="title function_">dfs</span>(<span class="params">node, visited</span>) {</span><br><span class="line"> <span class="keyword">if</span> (visited.<span class="title function_">has</span>(node)) {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 处理当前节点</span></span><br><span class="line"> visited.<span class="title function_">add</span>(node);</span><br><span class="line"> </span><br><span class="line"> <span class="comment">// 遍历当前节点的相邻节点</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> neighbor <span class="keyword">of</span> node.<span class="property">neighbors</span>) {</span><br><span class="line"> <span class="keyword">if</span> (!visited.<span class="title function_">has</span>(neighbor)) {</span><br><span class="line"> <span class="title function_">dfs</span>(neighbor, visited);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 初始化访问记录</span></span><br><span class="line"><span class="keyword">let</span> visited = <span class="keyword">new</span> <span class="title class_">Set</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">// 从起始节点开始进行DFS</span></span><br><span class="line"><span class="title function_">dfs</span>(startNode, visited);</span><br></pre></td></tr></table></figure>
<p>在这段代码中,<code>dfs()</code>函数表示深度优先搜索的递归函数,接受一个节点<code>node</code>和一个记录访问情况的<code>visited</code>集合作为参数。在DFS过程中,首先检查当前节点是否已经被访问过,如果已经访问过则直接返回;否则将当前节点标记为已访问,并递归地对当前节点的相邻节点进行DFS遍历。</p>
<p>用dfs,会超时,时间复杂度会达到2^(m+n)次,所以不合适,但是思路是可行的,如果m和n较小的话</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">m</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">n</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> uniquePaths = <span class="keyword">function</span>(<span class="params">m, n</span>) {</span><br><span class="line"> <span class="keyword">function</span> <span class="title function_">dfs</span>(<span class="params">x, y</span>) {</span><br><span class="line"> <span class="comment">// 如果越界,则认为这条路径不可行</span></span><br><span class="line"> <span class="keyword">if</span> (x >= m || y >= n) <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> <span class="comment">// 当到达终点时,返回1</span></span><br><span class="line"> <span class="keyword">if</span> (x === m - <span class="number">1</span> && y === n - <span class="number">1</span>) <span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"> <span class="comment">// 向右走 + 向下走</span></span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">dfs</span>(x + <span class="number">1</span>, y) + <span class="title function_">dfs</span>(x, y + <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">dfs</span>(<span class="number">0</span>, <span class="number">0</span>);</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h4 id="不同路径II"><a href="#不同路径II" class="headerlink" title="不同路径II"></a>不同路径II</h4><p><a href="https://leetcode.cn/problems/unique-paths-ii/">63. 不同路径 II</a></p>
<p>一个机器人位于一个 <code>m x n</code> 网格的左上角 (起始点在下图中标记为 “Start” )。</p>
<p>机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish”)。</p>
<p>现在考虑网格中有障碍物。那么从左上角到右下角将会有多少条不同的路径?</p>
<p>网格中的障碍物和空位置分别用 <code>1</code> 和 <code>0</code> 来表示。</p>
<p><strong>示例 1:</strong></p>
<p><img src="https://assets.leetcode.com/uploads/2020/11/04/robot1.jpg" alt="img"></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:obstacleGrid = [[0,0,0],[0,1,0],[0,0,0]]</span><br><span class="line">输出:2</span><br><span class="line">解释:3x3 网格的正中间有一个障碍物。</span><br><span class="line">从左上角到右下角一共有 2 条不同的路径:</span><br><span class="line">1. 向右 -> 向右 -> 向下 -> 向下</span><br><span class="line">2. 向下 -> 向下 -> 向右 -> 向右</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<p><img src="https://assets.leetcode.com/uploads/2020/11/04/robot2.jpg" alt="img"></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:obstacleGrid = [[0,1],[0,0]]</span><br><span class="line">输出:1</span><br></pre></td></tr></table></figure>
<p><strong>提示:</strong></p>
<ul>
<li><code>m == obstacleGrid.length</code></li>
<li><code>n == obstacleGrid[i].length</code></li>
<li><code>1 <= m, n <= 100</code></li>
<li><code>obstacleGrid[i][j]</code> 为 <code>0</code> 或 <code>1</code></li>
</ul>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number[][]</span>} <span class="variable">obstacleGrid</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> uniquePathsWithObstacles = <span class="keyword">function</span>(<span class="params">obstacleGrid</span>) {</span><br><span class="line"> <span class="comment">//当(x,y)点是障碍点时,那么达到x,y的路径只能是0条,多加一个判断条件</span></span><br><span class="line"> <span class="comment">//初始化d[x][y]</span></span><br><span class="line"> <span class="keyword">let</span> m = obstacleGrid.<span class="property">length</span>;</span><br><span class="line"> <span class="keyword">let</span> n = obstacleGrid[<span class="number">0</span>].<span class="property">length</span>;</span><br><span class="line"> <span class="keyword">let</span> d = <span class="keyword">new</span> <span class="title class_">Array</span>(m);</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> x = <span class="number">0</span>; x < m; x++){</span><br><span class="line"> d[x] = <span class="keyword">new</span> <span class="title class_">Array</span>(n);</span><br><span class="line"> <span class="keyword">let</span> y = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">while</span>(x==<span class="number">0</span> && obstacleGrid[<span class="number">0</span>][y]!=<span class="number">1</span> && y < n){</span><br><span class="line"> d[<span class="number">0</span>][y++] = <span class="number">1</span></span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">while</span>(x==<span class="number">0</span> && y < n){</span><br><span class="line"> d[<span class="number">0</span>][y++] = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(obstacleGrid[x][<span class="number">0</span>]!=<span class="number">1</span>){</span><br><span class="line"> d[x][<span class="number">0</span>] = <span class="number">1</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">while</span>(x < m){<span class="comment">//这里有个易错点</span></span><br><span class="line"> <span class="comment">//如果在这个代码块种不加if(x < m)d[x] = new Array(n);,那么因为当x++的时候,下一个d[x]是没有定义为数组的,如果此时使用d[x][0]就会报不能给undefined赋值的错误</span></span><br><span class="line"> d[x][<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"> x++;</span><br><span class="line"> <span class="keyword">if</span>(x < m)d[x] = <span class="keyword">new</span> <span class="title class_">Array</span>(n);</span><br><span class="line"> }</span><br><span class="line"> } </span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> x = <span class="number">1</span>; x < m; x++){</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> y = <span class="number">1</span>; y < n; y++){</span><br><span class="line"> <span class="keyword">if</span>(obstacleGrid[x][y]==<span class="number">1</span>){</span><br><span class="line"> d[x][y] = <span class="number">0</span>;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> d[x][y] = d[x-<span class="number">1</span>][y] + d[x][y-<span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(d);</span><br><span class="line"> <span class="keyword">return</span> d[m-<span class="number">1</span>][n-<span class="number">1</span>];</span><br><span class="line"></span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h4 id="整数拆分"><a href="#整数拆分" class="headerlink" title="整数拆分"></a>整数拆分</h4><p><a href="https://leetcode.cn/problems/integer-break/">343. 整数拆分</a></p>
<p>给定一个正整数 <code>n</code> ,将其拆分为 <code>k</code> 个 <strong>正整数</strong> 的和( <code>k >= 2</code> ),并使这些整数的乘积最大化。</p>
<p>返回 <em>你可以获得的最大乘积</em> 。</p>
<p><strong>示例 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入: n = 2</span><br><span class="line">输出: 1</span><br><span class="line">解释: 2 = 1 + 1, 1 × 1 = 1。</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入: n = 10</span><br><span class="line">输出: 36</span><br><span class="line">解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36。</span><br></pre></td></tr></table></figure>
<p><strong>提示:</strong></p>
<ul>
<li><code>2 <= n <= 58</code></li>
</ul>
<p><strong>code:</strong></p>
<p>把数尽量拆成平均的</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">n</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> integerBreak = <span class="keyword">function</span>(<span class="params">n</span>) {</span><br><span class="line"> <span class="keyword">let</span> maxNum = -<span class="number">1</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> k = <span class="number">2</span>; k <= n ; k++){</span><br><span class="line"> <span class="keyword">let</span> m = n % k;<span class="comment">//余数</span></span><br><span class="line"> maxNum = <span class="title class_">Math</span>.<span class="title function_">max</span>(((((n-m)/k) + <span class="number">1</span>))**(m) * (((n-m)/k)) ** (k - m), maxNum);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> maxNum;</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<p>dp思想:对于递推公式还是有点疑惑</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">n</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> integerBreak = <span class="keyword">function</span>(<span class="params">n</span>) {</span><br><span class="line"> <span class="comment">// 10 </span></span><br><span class="line"> <span class="comment">// 1 9</span></span><br><span class="line"> <span class="comment">// 2 8 </span></span><br><span class="line"> <span class="comment">// 3 7</span></span><br><span class="line"> <span class="comment">//4 6</span></span><br><span class="line"> <span class="comment">// 5 5</span></span><br><span class="line"> <span class="comment">// 6 4</span></span><br><span class="line"> <span class="comment">// 7 3</span></span><br><span class="line"> <span class="comment">// 8 2</span></span><br><span class="line"> <span class="comment">// 9 1</span></span><br><span class="line"> <span class="keyword">let</span> dp = <span class="keyword">new</span> <span class="title class_">Array</span>(n+<span class="number">1</span>).<span class="title function_">fill</span>(<span class="number">0</span>);<span class="comment">//要先提前初始化为0</span></span><br><span class="line"> dp[<span class="number">0</span>] = <span class="number">0</span>;</span><br><span class="line"> dp[<span class="number">1</span>] = <span class="number">0</span>;</span><br><span class="line"> dp[<span class="number">2</span>] = <span class="number">1</span>;</span><br><span class="line"> <span class="comment">// 3 </span></span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">3</span>; i <= n; i++){</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> j = <span class="number">1</span>; j <= i/<span class="number">2</span>; j++){</span><br><span class="line"> dp[i] = <span class="title class_">Math</span>.<span class="title function_">max</span>(j*(i-j), j*dp[i-j],dp[i]);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[n];</span><br><span class="line"></span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h4 id="不同的二叉搜索树"><a href="#不同的二叉搜索树" class="headerlink" title="不同的二叉搜索树"></a>不同的二叉搜索树</h4><p><a href="https://leetcode.cn/problems/unique-binary-search-trees/">96. 不同的二叉搜索树</a></p>
<p>给你一个整数 <code>n</code> ,求恰由 <code>n</code> 个节点组成且节点值从 <code>1</code> 到 <code>n</code> 互不相同的 <strong>二叉搜索树</strong> 有多少种?返回满足题意的二叉搜索树的种数。</p>
<p><strong>示例 1:</strong></p>
<p><img src="https://assets.leetcode.com/uploads/2021/01/18/uniquebstn3.jpg" alt="img"></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:n = 3</span><br><span class="line">输出:5</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:n = 1</span><br><span class="line">输出:1</span><br></pre></td></tr></table></figure>
<p><strong>提示:</strong></p>
<ul>
<li><code>1 <= n <= 19</code></li>
</ul>
<p><strong>Code:</strong></p>
<p>如果清楚二叉搜索树的特性和知道用动态规划来做这道题,这道题其实还不算特别难,但是需要画图分析一下,其实就是找规律的过程。</p>
<p>由于二叉搜索树的特性(比跟节点小的数一定放在左子树中,比根节点大的数一定放在右子树中),所以就需要考虑当<code>j</code>作为根节点的时候,会有几种情况,在对<code>j</code>从<code>0</code>遍历到<code>n</code>;这里为什么从<code>0</code>开始遍历,后面会解释。</p>
<p>在实际分析前,需要注意的一点的,如果一棵树只有3个节点,那无论这三个节点里面的数是(1,2,3),还是(2,3,4),或者是(11,12,13)等等,只要是连续的数字,那么他们的二叉搜索树的种类个数就一定是相等的。<code>即树有几种可能性是考虑树中有几个节点,而不是考虑树中节点的实际值。</code></p>
<p>具体来说,考虑n=4的情况,在n=4时,分为4种情况讨论:</p>
<ul>
<li><p>当root=1,那么可以得知对于2,3,4节点来说,这三个节点都将放在以<code>1</code>为根节点的树的右子树下,因为 2,3,4都大于1,那么对于右子树而言,只需要计算(2,3,4)节点的可能种类即<code>d[3]</code>;在考虑左子树,由于没有比1还小的树节点,所以此时的左子树是为空的,即<code>d[0]</code>。一般来说,如果考虑<code>d[0]</code>的实际意义,可能会给<code>d[0]</code>赋值为0;</p>
<p>但是需要考虑到,一棵树的种类,如果确定了根节点,那么这颗树的可能种类就是左子树的可能种类个数乘上右子树的可能种类个数,即<code>d[3]*d[0]</code>,如果我们给<code>d[0]</code>赋值为0,那么<code>d[3]*d[0]==0</code>,这很明显和实际情况不符。再加上题目中<code>1<=n<=19</code>,所以我们不妨将<code>d[0]</code>赋值为<code>1</code>。</p>
</li>
<li><p>那么当roo=2,我们同理分析,只有(<code>1</code>)节点(1个节点)在右子树中,而(<code>2,3</code>)节点(2个节点)在左子树中,那么可能性就是<code>d[1]*d[2]</code></p>
</li>
<li><p>同理,当root=3,有(<code>1,2</code>)2个节点在右子树,只有(<code>4</code>)1个节点在左子树中,所以可能性是<code>d[2]*d[1]</code></p>
</li>
<li><p>当root=4,有(<code>1,2,3</code>)3个节点在右子树,0个节点在左子树,即<code>d[3]*d[0]</code></p>
<p>总结分析得 <code>root==1 d[3]*d[0]</code></p>
<p>总结分析得 <code>root==2 d[2]*d[1]</code></p>
<p>总结分析得 <code>root==3 d[1]*d[2]</code></p>
<p>总结分析得 <code>root==4 d[0]*d[3]</code></p>
<p> 即 <code>root==j d[i-j-1]*d[j]</code>,<code>j</code>从<code>0</code>到<code>i-1</code>(0和i-1都去得到)</p>
<p>从实际意义上来理解其实也很好,如果是一颗有<code>i</code>个节点的树,其中一个节点已经确定了是根节点了,所以只有剩下的<code>i-1</code>个节点分别分配在左右子树中,所以左右子树的节点个数相加是<code>i-1</code>,所以上面的<code>d[i-j-1]*d[j]</code>中的<code>i-j-1</code>加上<code>j</code>是一定等于<code>i-1</code>的。</p>
</li>
</ul>
<p>现在只需要对上面的4种情况(<code>i==4</code>种情况)进行求和就可以得出<code>dp[4]</code>即<code>dp[i]</code></p>
<p>这种规律从<code>i=3</code>就开始了,所以可以从<code>i=3</code>开始遍历,一直到题目所求的<code>i==n</code></p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">n</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> numTrees = <span class="keyword">function</span>(<span class="params">n</span>) {</span><br><span class="line"> <span class="comment">//d[i]表示有i个节点的二叉搜索树的种数</span></span><br><span class="line"> <span class="keyword">let</span> dp = <span class="keyword">new</span> <span class="title class_">Array</span>(n+<span class="number">1</span>).<span class="title function_">fill</span>(<span class="number">1</span>);</span><br><span class="line"> dp[<span class="number">2</span>] = <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">3</span>; i <= n; i++){</span><br><span class="line"> <span class="keyword">let</span> cn = <span class="number">0</span>;</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> j = <span class="number">0</span>; j < i; j++){</span><br><span class="line"> cn += (dp[j] * dp[i-j-<span class="number">1</span>]);</span><br><span class="line"> }</span><br><span class="line"> dp[i] = cn;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> dp[n];</span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h3 id="背包问题"><a href="#背包问题" class="headerlink" title="背包问题"></a>背包问题</h3><h4 id="416-分割等和子集"><a href="#416-分割等和子集" class="headerlink" title="416. 分割等和子集"></a>416. 分割等和子集</h4><p><a href="https://leetcode.cn/problems/partition-equal-subset-sum/">416. 分割等和子集</a></p>
<p>给你一个 <strong>只包含正整数</strong> 的 <strong>非空</strong> 数组 <code>nums</code> 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。</p>
<p><strong>示例 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:nums = [1,5,11,5]</span><br><span class="line">输出:true</span><br><span class="line">解释:数组可以分割成 [1, 5, 5] 和 [11] 。</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:nums = [1,2,3,5]</span><br><span class="line">输出:false</span><br><span class="line">解释:数组不能分割成两个元素和相等的子集。</span><br></pre></td></tr></table></figure>
<p><strong>提示:</strong></p>
<ul>
<li><code>1 <= nums.length <= 200</code></li>
<li><code>1 <= nums[i] <= 100</code></li>
</ul>
<p><strong>思路</strong></p>
<p>取和不取的问题,对于一个正数数组,数组中所有值的和事确定的,所以分成两个子集后,两个子集的元素和就为整个和的一半</p>
]]></content>
<tags>
<tag>算法</tag>
<tag>动态规划</tag>
</tags>
</entry>
<entry>
<title>leetcode热题hot100</title>
<url>/2024/05/12/leetcode%E7%83%AD%E9%A2%98hot100/</url>
<content><![CDATA[<h1 id="leetcode热题hot100【JS】"><a href="#leetcode热题hot100【JS】" class="headerlink" title="leetcode热题hot100【JS】"></a>leetcode热题hot100【JS】</h1><h2 id="更新时间"><a href="#更新时间" class="headerlink" title="更新时间"></a>更新时间</h2><p>2024.5.12 第一次更新</p>
<p>2024.5.17 第二次更新</p>
<h2 id="刷算法题可能用到的函数和表示方式"><a href="#刷算法题可能用到的函数和表示方式" class="headerlink" title="刷算法题可能用到的函数和表示方式"></a>刷算法题可能用到的函数和表示方式</h2><h3 id="常用的表达方式"><a href="#常用的表达方式" class="headerlink" title="常用的表达方式"></a>常用的表达方式</h3><figure class="highlight js"><table><tr><td class="code"><pre><span class="line"><span class="comment">//2的10次方</span></span><br><span class="line"><span class="keyword">let</span> n = <span class="number">2</span> ** <span class="number">10</span>;</span><br></pre></td></tr></table></figure>
<h3 id="数组"><a href="#数组" class="headerlink" title="数组"></a>数组</h3><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">//数组中插入数据</span></span><br><span class="line"><span class="keyword">let</span> arr = [];</span><br><span class="line">arr.<span class="title function_">push</span>(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//arr = [1]</span></span><br><span class="line">arr.<span class="title function_">indexOf</span>(<span class="number">1</span>);<span class="comment">//0</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//比较两个数组是否相等(只适用于数组里面的元素都是原始值)</span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">arraysAreEqual</span>(<span class="params">array1, array2</span>) {</span><br><span class="line"> <span class="comment">// 首先检查数组长度</span></span><br><span class="line"> <span class="keyword">if</span> (array1.<span class="property">length</span> !== array2.<span class="property">length</span>) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 然后检查每个元素是否相等</span></span><br><span class="line"> <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i < array1.<span class="property">length</span>; i++) {</span><br><span class="line"> <span class="keyword">if</span> (array1[i] !== array2[i]) <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 如果通过了上述检查,那么数组相等</span></span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//数组遍历</span></span><br><span class="line"><span class="keyword">let</span> strs = [<span class="string">"hello"</span>, <span class="string">"world"</span>, <span class="string">"JavaScript"</span>];</span><br><span class="line"></span><br><span class="line"><span class="comment">//使用for循环</span></span><br><span class="line"><span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i < strs.<span class="property">length</span>; i++){</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(i,strs[i]);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//使用for of 与entries()</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> [i, str] <span class="keyword">of</span> strs.<span class="title function_">entries</span>()) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(i, str);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//数字数组的排序</span></span><br><span class="line"><span class="comment">//在JavaScript中,如果sort()方法没有提供比较函数,它会将数组元素转换成字符串,然后按照字符串的Unicode码点顺序进行排序。</span></span><br><span class="line"><span class="comment">//会导致例如这个数组[100,4,200,1,3,2]排序不成功</span></span><br><span class="line"><span class="comment">//例如,数字100和200在转换为字符串后,会根据它们的第一个字符("1"和"2")来进行排序,但当比较2和100时,由于"2"的Unicode码点小于"1"的Unicode码点,所以2会排在100之前。</span></span><br><span class="line"><span class="comment">//需要加入比较函数</span></span><br><span class="line">nums = [<span class="number">100</span>,<span class="number">4</span>,<span class="number">200</span>,<span class="number">1</span>,<span class="number">3</span>,<span class="number">2</span>];</span><br><span class="line">nums.<span class="title function_">sort</span>(<span class="function">(<span class="params">a, b</span>) =></span> a - b);</span><br><span class="line"><span class="comment">//这个比较函数简单地从a中减去b。如果结果是负数,那么a将排在b之前;如果结果是正数,b将排在a之前;如果结果是0,那么它们的顺序不变。</span></span><br><span class="line"><span class="comment">// a-b就是 从小到大排序</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//初始化一个长度为n,值为0的数组</span></span><br><span class="line"><span class="keyword">let</span> n = <span class="number">5</span>; <span class="comment">// 假设我们想要一个长度为5的数组</span></span><br><span class="line"><span class="keyword">let</span> arr = <span class="title class_">Array</span>(n).<span class="title function_">fill</span>(<span class="number">0</span>);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(arr); <span class="comment">// 输出: [0, 0, 0, 0, 0]</span></span><br></pre></td></tr></table></figure>
<h3 id="字符串"><a href="#字符串" class="headerlink" title="字符串"></a>字符串</h3><figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">//单个字符转换成ASCII码字</span></span><br><span class="line"><span class="keyword">let</span> c = <span class="string">'a'</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="title class_">ASCIINum</span> = c.<span class="title function_">charCodeAt</span>(<span class="number">0</span>);<span class="comment">//97</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> c1 = <span class="string">'ab'</span>;</span><br><span class="line"><span class="keyword">let</span> <span class="title class_">ASCIINum</span> = c.<span class="title function_">charCodeAt</span>(<span class="number">2</span>);<span class="comment">//98</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//将字符串分割成单个字符的数组</span></span><br><span class="line"><span class="keyword">let</span> str = <span class="string">"hello"</span>;</span><br><span class="line">str.<span class="title function_">split</span>(<span class="string">""</span>).<span class="title function_">forEach</span>(<span class="function"><span class="params">char</span> =></span> <span class="variable language_">console</span>.<span class="title function_">log</span>(char));</span><br><span class="line"><span class="comment">// ['h','e','l','l','o']</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//字符串字母排序 </span></span><br><span class="line"><span class="keyword">function</span> <span class="title function_">sortString</span>(<span class="params">str</span>) {</span><br><span class="line"> <span class="comment">// 将字符串转换为数组</span></span><br><span class="line"> <span class="keyword">let</span> arr = str.<span class="title function_">split</span>(<span class="string">''</span>);</span><br><span class="line"> <span class="comment">// 对数组进行排序</span></span><br><span class="line"> arr.<span class="title function_">sort</span>();</span><br><span class="line"> <span class="comment">// 将数组转换回字符串</span></span><br><span class="line"> <span class="keyword">return</span> arr.<span class="title function_">join</span>(<span class="string">''</span>);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">let</span> originalString = <span class="string">"hello"</span>;</span><br><span class="line"><span class="keyword">let</span> sortedString = <span class="title function_">sortString</span>(originalString);</span><br><span class="line"></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(sortedString); <span class="comment">// 输出: ehllo</span></span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="Map"><a href="#Map" class="headerlink" title="Map"></a>Map</h3><p>在JavaScript中,<code>Map</code> 是一种新的数据结构,它允许你存储键值对(key-value pairs)。与对象不同,<code>Map</code> 的键可以是任何类型的值,包括函数、对象或任何原始类型。下面是一些基本的 <code>Map</code> 对象用法:</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">//使用 `has` 方法可以检查 `Map` 中是否存在某个键:</span></span><br><span class="line"><span class="comment">//创建一个 Map</span></span><br><span class="line"><span class="keyword">let</span> map = <span class="keyword">new</span> <span class="title class_">Map</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">//设置键值对</span></span><br><span class="line"><span class="comment">//使用 `set` 方法可以添加或更新键值对:</span></span><br><span class="line">map.<span class="title function_">set</span>(<span class="string">'key'</span>, <span class="string">'value'</span>);</span><br><span class="line">map.<span class="title function_">set</span>(<span class="number">123</span>, <span class="number">456</span>);</span><br><span class="line">map.<span class="title function_">set</span>({}, <span class="string">'Object'</span>);</span><br><span class="line">map.<span class="title function_">set</span>(<span class="keyword">function</span>(<span class="params"></span>) {}, <span class="string">'Function'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//获取值</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(map.<span class="title function_">get</span>(<span class="string">'key'</span>)); <span class="comment">// 输出: 'value'</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(map.<span class="title function_">get</span>(<span class="number">123</span>)); <span class="comment">// 输出: 456</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//检查键是否存在</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(map.<span class="title function_">has</span>(<span class="string">'key'</span>)); <span class="comment">// 输出: true</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(map.<span class="title function_">has</span>(<span class="string">'notExist'</span>)); <span class="comment">// 输出: false</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//删除键值对</span></span><br><span class="line">map.<span class="title function_">delete</span>(<span class="string">'key'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//获取Map的大小</span></span><br><span class="line"><span class="comment">//使用 `size` 属性可以获取 `Map` 中键值对的数量:</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(map.<span class="property">size</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//遍历Map</span></span><br><span class="line"><span class="comment">//`Map` 对象可以通过 `forEach` 方法遍历,也可以使用迭代器方法(如 `keys()`, `values()`, 和 `entries()`)进行遍历。</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//使用 `forEach` 遍历:</span></span><br><span class="line">map.<span class="title function_">forEach</span>(<span class="function">(<span class="params">value, key</span>) =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(key, value);</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="comment">//使用迭代器遍历:</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> [key, value] <span class="keyword">of</span> map.<span class="title function_">entries</span>()) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(key, value);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">// 或者直接遍历Map对象</span></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> [key, value] <span class="keyword">of</span> map) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(key, value);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//清空Map</span></span><br><span class="line">map.<span class="title function_">clear</span>();</span><br><span class="line"></span><br></pre></td></tr></table></figure>
<h3 id="Set"><a href="#Set" class="headerlink" title="Set"></a>Set</h3><p>在JavaScript中,<code>Set</code>是一种新的数据结构,它类似于数组,但是它的一个主要特点是其内部的值都是唯一的,没有重复的值。<code>Set</code>对象允许你存储任何类型的唯一值,无论是原始值或是对象引用。</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">//创建一个 Set</span></span><br><span class="line"><span class="keyword">let</span> mySet = <span class="keyword">new</span> <span class="title class_">Set</span>();</span><br><span class="line"></span><br><span class="line"><span class="comment">//也可以在创建时初始化`Set`:</span></span><br><span class="line"><span class="keyword">let</span> mySet = <span class="keyword">new</span> <span class="title class_">Set</span>([<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">4</span>, <span class="number">4</span>]);</span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(mySet); <span class="comment">// Set(4) {1, 2, 3, 4}</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">//注意,即使数组中包含重复的元素,`Set`仍然确保只保存唯一的值。</span></span><br><span class="line"><span class="comment">//添加元素</span></span><br><span class="line">mySet.<span class="title function_">add</span>(<span class="number">5</span>);</span><br><span class="line">mySet.<span class="title function_">add</span>(<span class="string">"hello"</span>);</span><br><span class="line">mySet.<span class="title function_">add</span>({<span class="attr">a</span>: <span class="number">1</span>, <span class="attr">b</span>: <span class="number">2</span>});</span><br><span class="line"></span><br><span class="line"><span class="comment">//检查元素</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(mySet.<span class="title function_">has</span>(<span class="number">1</span>)); <span class="comment">// true</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(mySet.<span class="title function_">has</span>(<span class="number">6</span>)); <span class="comment">// false</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// 删除元素</span></span><br><span class="line">mySet.<span class="title function_">delete</span>(<span class="number">1</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//遍历 Set</span></span><br><span class="line"><span class="comment">//`Set`对象可以使用`forEach()`方法和`for...of`循环来遍历:</span></span><br><span class="line">mySet.<span class="title function_">forEach</span>(<span class="function"><span class="params">value</span> =></span> {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(value);</span><br><span class="line">});</span><br><span class="line"></span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">let</span> item <span class="keyword">of</span> mySet) {</span><br><span class="line"> <span class="variable language_">console</span>.<span class="title function_">log</span>(item);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//获取 Set 的大小</span></span><br><span class="line"><span class="variable language_">console</span>.<span class="title function_">log</span>(mySet.<span class="property">size</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">//清空 Set</span></span><br><span class="line">mySet.<span class="title function_">clear</span>();</span><br></pre></td></tr></table></figure>
<blockquote>
<p>Set是JavaScript ES6中引入的一种集合类型,它提供了一种存储唯一值的高效方式。</p>
</blockquote>
<h2 id="100题实战"><a href="#100题实战" class="headerlink" title="100题实战"></a>100题实战</h2><h3 id="哈希"><a href="#哈希" class="headerlink" title="哈希"></a>哈希</h3><h4 id="两数之和【数组、哈希】"><a href="#两数之和【数组、哈希】" class="headerlink" title="两数之和【数组、哈希】"></a>两数之和【数组、哈希】</h4><p><a href="https://leetcode.cn/problems/two-sum/">1. 两数之和</a></p>
<p>给定一个整数数组 <code>nums</code> 和一个整数目标值 <code>target</code>,请你在该数组中找出 <strong>和为目标值</strong> <em><code>target</code></em> 的那 <strong>两个</strong> 整数,并返回它们的数组下标。</p>
<p>你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。</p>
<p>你可以按任意顺序返回答案。</p>
<p><strong>示例 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:nums = [2,7,11,15], target = 9</span><br><span class="line">输出:[0,1]</span><br><span class="line">解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。</span><br></pre></td></tr></table></figure>
<p><strong>示例 2:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:nums = [3,2,4], target = 6</span><br><span class="line">输出:[1,2]</span><br></pre></td></tr></table></figure>
<p><strong>示例 3:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入:nums = [3,3], target = 6</span><br><span class="line">输出:[0,1]</span><br></pre></td></tr></table></figure>
<p><strong>提示:</strong></p>
<ul>
<li><code>2 <= nums.length <= 104</code></li>
<li><code>-109 <= nums[i] <= 109</code></li>
<li><code>-109 <= target <= 109</code></li>
<li><strong>只会存在一个有效答案</strong></li>
</ul>
<p><strong>code</strong>:</p>
<p>第一次写没有考虑到两个数的下标不能一样</p>
<figure class="highlight javascript"><table><tr><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number[]</span>} <span class="variable">nums</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> {<span class="type">number</span>} <span class="variable">target</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> {<span class="type">number[]</span>}</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">var</span> twoSum = <span class="keyword">function</span>(<span class="params">nums, target</span>) {</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">let</span> i = <span class="number">0</span>; i < nums.<span class="property">length</span>; i++){</span><br><span class="line"> <span class="keyword">let</span> res = [];</span><br><span class="line"> <span class="keyword">let</span> index;</span><br><span class="line"> <span class="keyword">if</span>(( index = nums.<span class="title function_">indexOf</span>(target - nums[i])) != -<span class="number">1</span> && index != i){</span><br><span class="line"> res.<span class="title function_">push</span>(i);</span><br><span class="line"> res.<span class="title function_">push</span>(index);</span><br><span class="line"> <span class="keyword">return</span> res;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line">};</span><br></pre></td></tr></table></figure>
<h4 id="字母异位词分组【数组、哈希、字符串】"><a href="#字母异位词分组【数组、哈希、字符串】" class="headerlink" title="字母异位词分组【数组、哈希、字符串】"></a>字母异位词分组【数组、哈希、字符串】</h4><p><a href="https://leetcode.cn/problems/group-anagrams/">49. 字母异位词分组</a></p>
<p>给你一个字符串数组,请你将 <strong>字母异位词</strong> 组合在一起。可以按任意顺序返回结果列表。</p>
<p><strong>字母异位词</strong> 是由重新排列源单词的所有字母得到的一个新单词。</p>
<p><strong>示例 1:</strong></p>
<figure class="highlight plaintext"><table><tr><td class="code"><pre><span class="line">输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]</span><br><span class="line">输出: [["bat"],["nat","tan"],["ate","eat","tea"]]</span><br></pre></td></tr></table></figure>