-
Notifications
You must be signed in to change notification settings - Fork 0
/
feed.xml
1640 lines (1591 loc) · 88.6 KB
/
feed.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'?>
<feed xmlns="http://www.w3.org/2005/Atom"><id>https://github.com/HealUP/MyBlog</id><title>RSS feed of HealUP's MyBlog</title><updated>2024-04-14T05:46:53.175431+00:00</updated><author><name>HealUP</name><email>[email protected]</email></author><link href="https://github.com/HealUP/MyBlog"/><link href="https://raw.githubusercontent.com/HealUP/MyBlog/master/feed.xml" rel="self"/><generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator><entry><id>https://github.com/HealUP/MyBlog/issues/45</id><title>10月份-11月份计划🍾</title><updated>2024-04-14T05:46:53.364485+00:00</updated><content type="html"><![CDATA[<h2>行动是解决焦虑的最好方式!💪</h2>
<ul>
<li><input checked="" disabled="" type="checkbox"> 坚持投简历 -> 找工作(<strong>实习转正</strong>)</li>
<li><input checked="" disabled="" type="checkbox"> 毕业设计代码开发达到60%</li>
<li><input checked="" disabled="" type="checkbox"> 持续技术学习->输出技术文档(一周至少3篇)</li>
<li><input checked="" disabled="" type="checkbox"> 开源项目(整理core项目并开源)</li>
<li><input checked="" disabled="" type="checkbox"> 软考备考</li>
<li><input checked="" disabled="" type="checkbox"> 一周3跑 (至少5k)</li>
<li><input checked="" disabled="" type="checkbox"> 10-11月份总结复盘</li>
</ul>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/45"/><category term="TODO"/><published>2023-10-21T09:04:12+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/44</id><title>8月份计划🗓️</title><updated>2024-04-14T05:46:53.436880+00:00</updated><content type="html"><![CDATA[<p>八月份已经过得差不多了,补充下八月份的计划</p>
<h2></h2>
<ul>
<li><input checked="" disabled="" type="checkbox"> 准备面试(八股)模拟面试</li>
<li><input checked="" disabled="" type="checkbox"> 完成公司项目开发并上线</li>
<li><input checked="" disabled="" type="checkbox"> 毕设提前了解,确定选题</li>
<li><input checked="" disabled="" type="checkbox"> 算法训练</li>
<li><input checked="" disabled="" type="checkbox"> 熟悉项目</li>
<li><input checked="" disabled="" type="checkbox"> 看一本书</li>
<li><input checked="" disabled="" type="checkbox"> 完成实习的周记</li>
<li><input checked="" disabled="" type="checkbox"> 单词500</li>
</ul>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/44"/><category term="TODO"/><published>2023-08-21T13:47:43+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/42</id><title>UML图</title><updated>2024-04-14T05:46:53.506568+00:00</updated><content type="html"><![CDATA[<h2>UML图</h2>
<p>统一建模语言(Unified Modeling Language,缩写UML)是非专利的第三代建模和规约语言。
UML是一种开放的方法,用于说明、可视化、构建和编写一个正在开发的、面向对象的、软件密集系统的制品的开放方法。
分类:
● UML模型
○ 功能模型:从用户的角度展示系统的功能,包括用例图。
○ 对象模型:采用对象,属性,操作,关联等概念展示系统的结构和基础,包括类别图、对象图。
○ 动态模型:展现系统的内部行为。包括序列图,活动图,状态图。
● UML图
○ 结构性图形(Structure diagrams)强调的是系统式的建模:
■ 静态图(static diagram):包括类图、对象图、包图
■ 实现图(implementation diagram):包括组件图、部署图
■ 剖面图
■ 复合结构图
○ 行为式图形(Behavior diagrams)强调系统模型中触发的事件
■ 活动图
■ 状态图
■ 用例图
○ 交互性图形(Interaction diagrams),属于行为图形的子集合,强调系统模型中的资料流程
■ 通信图
■ 交互概述图
■ 时序图
■ 时间图
下面详细讲解类图</p>
<h3>类图</h3>
<p>作用:解析项目的系统结构和架构层次,可以简洁明了的帮助我们理解项目中类之间的关系。
类图的格式:
● 类名:粗体(类是抽象类则类名显示为斜体)
● 属性:
○ 格式:可见性 名称:类型[=默认值]
○ 可见性一般为public、private和protected,在类图分别用+、-和#表示
● 方法:
○ 格式:可见性 名称(参数列表 参数1,参数2) :返回类型
■ 可见性如上名称表达式的介绍
■ 名称就是方法名
■ 参数列表是可选的项,多参数的话参数直接用英文逗号隔开
■ 返回值也是个可选项,返回值类型可以说基本的数据类型、用户自定义类型和void。(如果是构造方法,则无返回类型)
<img src="https://s2.loli.net/2023/07/29/vPLJzXZ4nfWiFEM.png" alt="image.png" /></p>
<p>类与类之间的关系:
泛化(继承)、实现、依赖、关联、聚合、组合
<img src="https://s2.loli.net/2023/07/29/Tqj1ANIREk9rg5B.png" alt="image.png" /></p>
<p>聚合:部分可以脱离整理而存在
组合:部分若脱离了整体,则不复存在
关联:长期性的
依赖:临时性的</p>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/42"/><category term="设计模式"/><published>2023-07-29T15:11:47+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/41</id><title>28. 找出字符串中第一个匹配项的下标——KMP算法</title><updated>2024-04-14T05:46:53.581383+00:00</updated><content type="html"><![CDATA[<p>KMP算法
<strong>28. 找出字符串中第一个匹配项的下标</strong></p>
<blockquote>
<p>思路:使用KMP算法,<strong>一定要构造next数组</strong>(即前缀表)</p>
</blockquote>
<ul>
<li>next数组,就是以模式串中各个字符串结尾的最长相等前后缀的集合</li>
</ul>
<blockquote>
<p>KMP算法 1.构造next数组(和模式串大小一致) 2.模式串用next数组匹配文本串</p>
<p>那怎么构造next数组呢,思路:</p>
</blockquote>
<blockquote>
<p>1.初始化 2.处理前后缀不相同的情况 3.处理前后缀相同的情况</p>
</blockquote>
<p><strong>注:以下统称haystack为文本串, needle为模式串</strong></p>
<blockquote>
<p>时间复杂度:其<strong>中n为文本串长度,m为模式串长度,因为在匹配的过程中,根据前缀表不断调整匹配的位置,可以看出匹配的过程是O(n),之前还要单独生成next数组,时间复杂度是O(m)。时间复杂度是O(n+m)</strong>。</p>
</blockquote>
<p>法一:前缀表不减一</p>
<pre><code>class Solution {
public int strStr(String haystack, String needle) {
//前后缀不减一的实现方式
//边界判断
if (needle.length() == 0) return 0;
int[] next = new int[needle.length()];//创建一个和模式串一样大的next数组
getNext(next, needle);//得到填充好的next数组
//使用next数组来做匹配 在文本串里找是否出现过模式串
//定义两个下标,j指向模式串起始位置,i指向文本串起始位置
int j = 0;//和next数组中j的起始位置对应
for (int i = 0; i < haystack.length(); i++) {
//不匹配的情况
while (j > 0 && needle.charAt(j) != haystack.charAt(i)) {//模式串的j>0,=0的话,下面的next就是next[-1]就出界了
//找到回退的位置,即改变前缀末尾的位置j
j = next[j - 1];
}
if (needle.charAt(j) == haystack.charAt(i)) {
j++;//前缀末尾后移
}
//判断在文本串s里出现了模式串t呢,如果j指向了模式串t的末尾,那么就说明模式串t完全匹配文本串s里的某个子串了
if (j == needle.length()) {
return i - needle.length() + 1;//因为返回的是下标,所以要+1;比如:长度是3,其最大下标就是2,数组下标从0开始的
}
}
//跳出循环了,说明找不到匹配的模式串的了
return -1;
}
//构造next数组
/*
思路:1.初始化
2.处理前后缀不相同的情况
3.处理前后缀相同的情况
*/
private void getNext(int[] next, String s) {
//定义两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置
//next[i] 表示 i(包括i)之前最长相等的前后缀长度(其实就是j)
//next[j]就是记录着j(包括j)之前的子串的相同前后缀的长度
int j = 0;
next[0] = j;
for (int i = 1; i < s.length(); i++) {//从1开始,因为0的位置肯定是0的,只有一个字符的时候,不存在相等的前后缀
//不相等前后缀的情况,回退 这里用while 是因为只要不相等就一致回退到相等或者到索引为1的位置
while (j > 0 && s.charAt(j) != s.charAt(i)) {
//改变前缀的末尾
j = next[j - 1];//不匹配字符的上一个位置
}
// 找到相同的前后缀
if (s.charAt(j) == s.charAt(i)) {
j++;//索引为i的位置的值加1
next[i] = j;//更新当前下标为i的next数组
}
}
}
}
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/41"/><category term="算法"/><published>2023-07-10T23:59:55+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/40</id><title>单例模式</title><updated>2024-04-14T05:46:53.662180+00:00</updated><content type="html"><![CDATA[<p><strong>单例模式类图展示:</strong>
<img src="https://s2.loli.net/2023/07/11/7RVzkAmlCKx6bJw.png" alt="image.png" /></p>
<blockquote>
<p>单例模式就是一个类只能有一个对象
使用场景:</p>
<ul>
<li>你希望这个类只有一个且只能有一个实例;</li>
<li>项目中的一些全局管理类(Manager)可以用单例来实现。</li>
</ul>
</blockquote>
<p><strong>下面要介绍的几种单例模式的实现方式</strong>:
<img src="https://s2.loli.net/2023/07/11/pCnm6Ihukj9LRDz.png" alt="image.png" /></p>
<p><strong>饿汉式</strong>:
步骤一:</p>
<pre><code>public class SingleObject {
private static SingleObject instance = new SingleObject();
// 构造函数为private,避免被实例化
private SingleObject(){};
// 获取唯一可用的对象
public static SingleObject getInstance() {
return instance;
}
public showMessage(){
System.out.println("hello guy!");
}
}
</code></pre>
<p>步骤二:</p>
<pre><code>public class SingleObjectDemo {
public static void main(String[] args) {
// 获取唯一可用的对象
SingleObject object = SingleObject.getInstance();
// 调用方法
object.showMessage();
}
}
</code></pre>
<p>步骤三:
<code>hello guy!</code></p>
<blockquote>
<p>以上就是饿汉式的实现方式,优点是没有加锁,执行效率高;支持多线程(利用的是JVM的类加载机制,在类初始化时就已经被加载,保证同一时刻只有一个线程获取到实例)
<strong>ps:这种方式是最常用的,但是容易产生垃圾对象</strong></p>
</blockquote>
<p><strong>懒汉式-线程安全</strong></p>
<pre><code>public class SingleObject {
private static SingleObject instance;
private SingleObject(){};
public static synchronized SingleObject getInstance() {
if (instance = null) {
instance = new SingleObject();
}
return instance;
}
}
</code></pre>
<blockquote>
<p>ps:优点是支持多线程,lazy加载(一开始先不实例化可以避免内存的浪费);必须使用但是使用synchronized才能保证单例,但是加了加锁操作,效率比较低,99%情况下是不需要同步的,不推荐使用。</p>
</blockquote>
<p><strong>懒汉式—线程不安全</strong></p>
<pre><code>public class SingleObject {
private static SingleObject instance;
private SingleObject(){};
public static SingleObject getInstance() {
if (instance = null) {
instance = new SingleObject();
}
return instance;
}
}
</code></pre>
<blockquote>
<p>ps:这种方式是最基本的实现方式,这种实现最大的问题就是<strong>不支持多线程</strong>。因为<strong>没有加锁 synchronized</strong>,所以严格意义上它并不算单例模式。</p>
</blockquote>
<p><strong>双检锁(DCL,即 double-checked locking)</strong></p>
<pre><code>public class Singleton {
private volatile static Singleton singleton;
private Singleton (){}
public static Singleton getSingleton() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
</code></pre>
<blockquote>
<p>ps:多了volatile,同时,又用了synchronized,这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
使用场景:getInstance() 的性能对应用程序很关键。</p>
</blockquote>
<p><strong>登记式</strong></p>
<pre><code>public class Singleton {
private static class SingletonHolder{
private static final Singleton INSTANCE = new Singleton();
}
private Singleton(){};
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
</code></pre>
<blockquote>
<p>PS:使用了静态内部类,这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于<strong>静态域</strong>的情况,双检锁方式可在实例域需要延迟初始化时使用。</p>
</blockquote>
<blockquote>
<p>解释:这种方式同样利用了 classloader 机制来保证初始化 instance 时只有一个线程,它跟饿汉式方式不同的是:饿汉式只要 Singleton 类被装载了,那么 instance 就会被实例化(没有达到 lazy loading 效果);而这种方式是 Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,<strong>只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。</strong></p>
</blockquote>
<blockquote>
<p>使用场景:如果实例化 instance 很消耗资源,所以想让它延迟加载,另外一方面,又不希望在 Singleton 类加载时就实例化,因为不能确保 Singleton 类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化 instance 显然是不合适的。这个时候,这种方式相比饿汉式就显得比较合理</p>
</blockquote>
<p><strong>枚举</strong></p>
<pre><code>public enum Singleton {
INSTANCE;
public void whateverMethod() {
}
}
</code></pre>
<p>总结::一般情况下,不建议使用懒汉方式,<strong>建议使用饿汉方式</strong>(<strong>线程安全,但没有懒加载</strong>)。只有在要<strong>明确实现 lazy loading 效果</strong>时,才会使用<strong>登记方式</strong>。如果涉及到<strong>反序列化创建对象</strong>时,可以尝试使用枚举方式。如果有其他特殊的需求,可以考虑使用双检锁方式。</p>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/40"/><category term="设计模式"/><published>2023-07-10T23:22:59+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/39</id><title>策略模式</title><updated>2024-04-14T05:46:53.733145+00:00</updated><content type="html"><![CDATA[<p>1.UML图
统一建模语言(Unified Modeling Language,缩写UML)是非专利的第三代建模和规约语言。
UML是一种开放的方法,用于说明、可视化、构建和编写一个正在开发的、面向对象的、软件密集系统的制品的开放方法。
分类:
● UML模型
○ 功能模型:从用户的角度展示系统的功能,包括用例图。
○ 对象模型:采用对象,属性,操作,关联等概念展示系统的结构和基础,包括类别图、对象图。
○ 动态模型:展现系统的内部行为。包括序列图,活动图,状态图。
● UML图
○ 结构性图形(Structure diagrams)强调的是系统式的建模:
■ 静态图(static diagram):包括类图、对象图、包图
■ 实现图(implementation diagram):包括组件图、部署图
■ 剖面图
■ 复合结构图
○ 行为式图形(Behavior diagrams)强调系统模型中触发的事件
■ 活动图
■ 状态图
■ 用例图
○ 交互性图形(Interaction diagrams),属于行为图形的子集合,强调系统模型中的资料流程
■ 通信图
■ 交互概述图
■ 时序图
■ 时间图
下面详细讲解类图
1.1 类图
作用:解析项目的系统结构和架构层次,可以简洁明了的帮助我们理解项目中类之间的关系。
类图的格式:
● 类名:粗体(类是抽象类则类名显示为斜体)
● 属性:
○ 格式:可见性 名称:类型[=默认值]
○ 可见性一般为public、private和protected,在类图分别用+、-和#表示
● 方法:
○ 格式:可见性 名称(参数列表 参数1,参数2) :返回类型
■ 可见性如上名称表达式的介绍
■ 名称就是方法名
■ 参数列表是可选的项,多参数的话参数直接用英文逗号隔开
■ 返回值也是个可选项,返回值类型可以说基本的数据类型、用户自定义类型和void。(如果是构造方法,则无返回类型)
<img src="https://s2.loli.net/2023/07/06/I5lK6upCMzUgXBj.png" alt="image.png" />
类与类之间的关系:
泛化(继承)、实现、依赖、关联、聚合、组合
<img src="https://github.com/HealUP/MyBlog/assets/72082506/19d2dd4e-be9a-4fdb-9c93-cc2fbf908369" alt="image" />
聚合:部分可以脱离整理而存在
组合:部分若脱离了整体,则不复存在
关联:长期性的
依赖:临时性的
2.设计模式
2.1 策略模式
<img src="https://s2.loli.net/2023/07/06/celMypUdXnuF1zv.png" alt="image.png" />
定义一系列算法,将每个算法都封装起来,并且使他们之间可以相互替换。策略模式使算法可以独立于使用它的用户而变化(聚合)
策略模式的结构:
● 环境(Context)角色: 持有一个Strategy的引用;
● 抽象策略(Strategy)角色: 这是一个抽象角色,通常由一个接口或抽象类实现。此角色给出所有的具体策略类所需的接口;(关系是:实现或继承)
● 具体策略(ConcreteStrategy)角色: 包装了相关的算法或行为
使用步骤:(举例)
● 定义Strategy接口,包含抽象方法 </p>
<pre><code>public interface Strategy {
public int doOperation(int num1, int num2);
}
</code></pre>
<p>● 创建实现接口的实体类:分别是加、减、乘的类,里面封装了这三种算法</p>
<pre><code>public class OperationAdd implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 + num2;
}
}
public class OperationSubtract implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 - num2;
}
}
public class OperationMultiply implements Strategy{
@Override
public int doOperation(int num1, int num2) {
return num1 * num2;
}
}
</code></pre>
<p>● 创建 Context 类 (Strategy类是Context的一部分——聚合关系)</p>
<pre><code>public class Context {
private Strategy strategy;// Strategy类是Context的一部分
// 有参构造
public Context(Strategy strategy){
this.strategy = strategy;
}
public int executeStrategy(int num1, int num2){
return strategy.doOperation(num1, num2);
}
}
</code></pre>
<p>● 使用Context来改变策略,达到使用不同代码逻辑的作用</p>
<pre><code>public class StrategyPatternDemo {
public static void main(String[] args) {
Context context = new Context(new OperationAdd());
System.out.println("10 + 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationSubtract());
System.out.println("10 - 5 = " + context.executeStrategy(10, 5));
context = new Context(new OperationMultiply());
System.out.println("10 * 5 = " + context.executeStrategy(10, 5));
}
}
</code></pre>
<p>结果:</p>
<pre><code>10 + 5 = 15
10 - 5 = 5
10 * 5 = 50
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/39"/><category term="设计模式"/><published>2023-07-06T00:04:03+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/38</id><title>🗓️7月份计划</title><updated>2024-04-14T05:46:53.809625+00:00</updated><content type="html"><![CDATA[<ul>
<li><input checked="" disabled="" type="checkbox"> 熟悉公司项目🧑💻⭐⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> 结合项目持续学习redis🧑💻⭐⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> 设计模式🧑💻⭐⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> Mysql总结输出🧑💻⭐⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> 微服务架构持续学习🧑💻⭐⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> 业务文档整理、技术方案总结,文字表达能力🧑💻⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> JVM学习+总结排错思路🧑💻 ⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> 出一版新的简历内容⭐⭐⭐⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> 英语听力+单词🚇⭐⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> 算法+SQL⭐⭐</li>
<li><input checked="" disabled="" type="checkbox"> 月度总结❗</li>
</ul>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/38"/><category term="TODO"/><published>2023-07-01T15:20:19+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/37</id><title>索引✅</title><updated>2024-04-14T05:46:53.877278+00:00</updated><content type="html"><![CDATA[<h1>1.索引</h1>
<h2>1.1 创建索引的方式</h2>
<p>索引就是用来帮助表快速检索目标数据的
那么,索引有哪几种创建方式:
● CREATE</p>
<blockquote>
<p>CREATE INDEX indexName ON tableName (columnName(length) [ASC|DESC]);
indexName:当前创建的索引,创建成功后索引的名字;
tableName:要在哪张表上创建一个索引,这里指定表名;
columnName:要为表中的哪个字段创建索引,这里指定字段名;
length:如果字段存储的值过长,选用值的前多少个字符创建索引;
ASC|DESC:指定索引的排序方式,ASC是升序,DESC是降序,默认ASC</p>
</blockquote>
<p>● ALTER
<code>ALTER TABLE tableName ADD INDEX indexName(columnName(length) [ASC|DESC]);</code></p>
<p>● DDL (建表时创建索引)适合已经确定了索引项的情况下建立</p>
<pre><code>CREATE TABLE tableName(
columnName1 INT(8) NOT NULL,
columnName2 ....,
.....,
INDEX [indexName] (columnName(length))
);
</code></pre>
<p>不同的索引有不同的创建方式:(后面会具体介绍各类索引)</p>
<p>● 唯一索引</p>
<pre><code>-- 方式①
CREATE UNIQUE INDEX indexName ON tableName (columnName(length));
-- 方式②
ALTER TABLE tableName ADD UNIQUE INDEX indexName(columnName);
-- 方式③
CREATE TABLE tableName(
columnName1 INT(8) NOT NULL,
columnName2 ....,
.....,
UNIQUE INDEX [indexName] (columnName(length))
);
</code></pre>
<p>● 主键索引</p>
<pre><code>-- 方式①
ALTER TABLE tableName ADD PRIMARY KEY indexName(columnName);
-- 方式②
CREATE TABLE tableName(
columnName1 INT(8) NOT NULL,
columnName2 ....,
.....,
PRIMARY KEY [indexName] (columnName(length))
);
</code></pre>
<p>● 全文索引——不常用</p>
<pre><code>-- 方式①
ALTER TABLE tableName ADD FULLTEXT INDEX indexName(columnName);
-- 方式②
CREATE FULLTEXT INDEX indexName ON tableName(columnName);
</code></pre>
<blockquote>
<p>注意点:
○ 5.6版本的MySQL中,存储引擎必须为MyISAM才能创建。
○ 创建全文索引的字段,其类型必须要为CHAR、VARCHAR、TEXT等文本类型。
○ 如果想要创建出的全文索引支持中文,需要在最后指定解析器:with parser ngram。
○ 优化器无法自动选择全文索引,他有自己的语法</p>
</blockquote>
<p>● 空间索引(仅有MyISAM支持空间索引)—— 不常用
<code>ALTER TABLE tableName ADD SPATIAL KEY indexName(columnName);</code></p>
<blockquote>
<p>注意:空间索引必须要建立在类型为GEOMETRY、POINT、LINESTRING、POLYGON的字段上
● 联合索引
○ 联合索引的意思是可以使用多个字段建立索引。那该如何创建联合索引呢,不需要特殊的关键字,方法如下:</p>
</blockquote>
<pre><code>CREATE INDEX indexName ON tableName (column1(length),column2...);
ALTER TABLE tableName ADD INDEX indexName(column1(length),column2...);
</code></pre>
<blockquote>
<p>注意:
● 使用联合索引时,SELECT语句的查询条件中,必须包含组成联合索引的第一个字段,此时才会触发联合索引,否则是无法使用联合索引的。
● 创建主键索引时,必须要将索引字段先设为主键,否则会抛1068错误码。
● 这里也不能使用CREATE(指方式①)语句创建索引,否则会提示1064语法错误。不过:一般主键索引都会在建表的DDL语句中创建,不会在表已经建立后再创建
● 同时创建索引时,关键字要换成KEY,并非INDEX,否则也会提示语法错误。</p>
</blockquote>
<h2>1.2 操作索引</h2>
<p>● 查看索引
<code>SHOW INDEX FROM tableName</code>
<img src="https://s2.loli.net/2023/06/11/TDKwlYby4prcE38.png" alt="image.png" />
<strong>每个字段的含义</strong>:</p>
<blockquote>
<p>● ①Table:当前索引属于那张表。
● ②Non_unique:目前索引是否属于唯一索引,0代表是的,1代表不是。
● ③Key_name:当前索引的名字。
● ④Seq_in_index:如果当前是联合索引,目前字段在联合索引中排第几个。
● ⑤Column_name:当前索引是位于哪个字段上建立的。
● ⑥Collation:字段值以什么方式存储在索引中,A表示有序存储,NULL表无序。
● ⑦Cardinality:当前索引的散列程度,也就是索引中存储了多少个不同的值。
● ⑧Sub_part:当前索引使用了字段值的多少个字符建立,NULL表示全部。
● ⑨Packed:表示索引在存储字段值时,以什么方式压缩,NULL表示未压缩,
● ⑩Null:当前作为索引字段的值中,是否存在NULL值,YES表示存在。
● ⑪Index_type:当前索引的结构(BTREE, FULLTEXT, HASH, RTREE)。
● ⑫Comment:创建索引时,是否对索引有备注信息。
<strong>后续排除问题、性能调优时,可以通过分析其中的Cardinality字段值,如果该值少于数据的实际行数,那目前索引有可能失效</strong>
● 如果新建错了索引,只能删除再重新创建
DROP INDEX indexName ON tableName;
● 指定索引
<code>SELECT * FROM table_name FORCE INDEX(index_name) WHERE .....;</code>
<strong>这个关键字的用法是:当一条查询语句在有多个索引可以检索数据时,显式指定一个索引,减少优化器选择索引的耗时。但是如果对业务系统不熟悉,还是得让优化器自己来选择。</strong></p>
</blockquote>
<h2>1.3 索引的本质</h2>
<blockquote>
<p>数据库是基于磁盘工作的,所有数据都再磁盘上面存储,索引也是数据的一种,同样存储在磁盘上,但是索引最终会以哪种方式进行存储,这是由索引的数据结构来决定的,同时索引机制又是由存储引擎实现的,不同的存储引擎下的索引文件,保存在本地的格式是不同的。
当数据量越少时,创建索引越好 ,因为创建索引时,会基于原有的数据重新在本地创建索引文件,并同时做好排序并与表数据产生映射的关系。</p>
</blockquote>
<h2>1.4索引的分类</h2>
<p>● 数据结构层次划分
○ B+Tree类型:MySQL中最常用的索引结构,大部分引擎支持,有序
○ Hash类型:大部分存储引擎都支持,字段值不重复的情况下查询最快,无序
○ R-Tree类型:MyISAM引擎支持,也就是空间索引的默认结构类型
○ T-Tree类型:NDB-Cluster引擎支持,主要用于MySQL-Cluster服务中</p>
<blockquote>
<p>B+树和哈希索引是最常见的索引结构,B+Tree是有序的,哈希是无序的。在MySQL中创建索引时,其默认的数据结构就为B+Tree,可以在建表时使用using字段改变索引的数据结构。
<code>CREATE INDEX indexName ON tableName (columnName(length) [ASC|DESC]) USING HASH;</code>
● 字段数量的层次划分
○ 单列索引
■ 主键索引
■ 唯一索引
■ 普通索引
○ 多列索引
■ 联合索引、组合索引、复合索引 、多值索引...很多种叫法,本质即由多个字段组成的索引</p>
</blockquote>
<blockquote>
<p>使用多列索引的注意事项:当建立多列索引后,一条SELECT语句,只有当查询条件中了包含了多列索引的第一个字段时,才能使用多列索引
● 使用一个字段值中的前N个字符创建出的索引,就可以被称为前缀索引 (length指定长度)
前缀索引能够在很大程度上,节省索引文件的存储空间,也能很大程度上提升索引的性能
● 功能逻辑层次划分
○ 普通索引、唯一索引、主键索引、全文索引、空间索引
● 存储方式划分
○ 聚簇索引:也被称为聚集索引、簇类索引
■ 逻辑上连续且物理空间上的连续
○ 非聚簇索引:也叫非聚集索引、非簇类索引、二级索引、辅助索引、次级索引
■ 逻辑上的连续,物理空间上不连续</p>
</blockquote>
<p><strong>注意:</strong></p>
<blockquote>
<p>1.一张表中只能存在一个聚簇索引,一般都会选用主键作为聚簇索引,其他字段上建立的索引都属于非聚簇索引,或者称之为辅助索引、次级索引。
2.误区:虽然MySQL默认会使用主键上建立的索引作为聚簇索引,但也可以指定其他字段上的索引为聚簇索引,一般聚簇索引要求索引必须是非空唯一索引才行。
3.如果表中就算没有定义主键,InnoDB中会选择一个唯一的非空索引作为聚簇索引,但如果非空唯一索引也不存在,InnoDB隐式定义一个主键来作为聚簇索引(一般适合采用带有自增性的顺序值)。</p>
</blockquote>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/37"/><category term="MySQL"/><published>2023-06-11T15:45:50+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/35</id><title>🗓️6月份计划</title><updated>2024-04-14T05:46:53.962384+00:00</updated><content type="html"><![CDATA[<h1>👣
热爱生活,感受当下!加油!🌝</h1>
<ul>
<li><input checked="" disabled="" type="checkbox"> 找到一份Java后端的实习岗位</li>
<li><input checked="" disabled="" type="checkbox"> 持续跟进学校工作室项目,按时完成交付</li>
<li><input checked="" disabled="" type="checkbox"> 熟悉公司业务(尽快上手开发)</li>
<li><input checked="" disabled="" type="checkbox"> 备考六级</li>
<li><input checked="" disabled="" type="checkbox"> 总结面试经验</li>
<li><input checked="" disabled="" type="checkbox"> 持续学习并输出学习blog</li>
<li>算法(贪心+回顾前面总结)</li>
<li>redis</li>
<li>MySQL进阶</li>
<li>Dubbo&Zookeeper</li>
<li>设计模并运用到项目</li>
<li><input checked="" disabled="" type="checkbox"> 八股文持续总结输出</li>
</ul>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/35"/><category term="TODO"/><published>2023-06-02T14:55:22+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/33</id><title>快速排序⭐⭐⭐</title><updated>2024-04-14T05:46:54.077121+00:00</updated><content type="html"><![CDATA[<p>理论基础:快速排序是一种常见的排序算法,使用分治的思想来排序一个数组或列表。它的基本思想是选择一个<strong>基准数</strong>,<strong>将数组分成两个部分</strong>,一部分是小于基准数的,另一部分是大于等于基准数的,然后再对这两部分递归地进行排序</p>
<p>时间复杂度:nlogn</p>
<p>具体步骤如下:</p>
<ol>
<li>选择一个基准数(pivot),可以选择第一个数、最后一个数、中间的数或者随机数。</li>
<li>将数组中<strong>小于等于</strong>基准数的元素放在基准数的左边,大于基准数的元素放在基准数的右边,这一步称为**“划分**”(partition)操作。</li>
<li>对基准数左边的子数组进行<strong>递归</strong>排序,对基准数右边的子数组进行<strong>递归排序</strong>,直到每个子数组的长度为 0 或 1,排序完成。</li>
</ol>
<pre><code class="language-JAVA">class Solution {
public int[] sortArray(int[] nums) {
quickSort(nums, 0, nums.length - 1);
return nums;
}
// 快速排序函数
public static int[] quickSort(int[] nums, int left, int right) {
if (left >= right) {
return null;
}
int partition = partition(nums, left, right);
quickSort(nums, left, partition - 1);//在划分位置的左边子区域再划分,直到不可划分left >= right不能进循环条件
quickSort(nums, partition + 1, right); //在划分位置的右边子区域再划分,直到不可划分left >= right不能进循环条件
return nums;
}
public static int partition(int[] nums, int left, int right) {
int pivot = nums[left];
while (left < right) {
while (left < right && nums[right] >= pivot) {
right--;
}
nums[left] = nums[right];
while (left < right && nums[left] <= pivot) {
left++;
}
nums[right] = nums[left];
}
nums[left] = pivot; //当前left,right 指向同一个位置了 nums[right] = pivot也行
return left;// 返回划分的位置
}
}
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/33"/><category term="算法"/><published>2023-05-24T15:36:17+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/32</id><title>LC 111. 二叉树的最小深度</title><updated>2024-04-14T05:46:54.144506+00:00</updated><content type="html"><![CDATA[<h3>111. 二叉树的最小深度</h3>
<blockquote>
<p>思路:遍历每一层的时候,记录次数;当该节点的左右节点都为空的时候,直接返回当前的深度即可,如果左右节点不为空就加入队列</p>
</blockquote>
<pre><code class="language-java">class Solution {
public int minDepth(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
int min = 0;
while (!que.isEmpty()) {
int len = que.size();
min++;
for (int i = 0; i < len; i++) {
TreeNode node = que.poll();
if (node.left == null && node.right == null) {
return min;//该节点的左右节点大都为空直接返回当前的深度
}
//加入该节点的左右节点
if (node.left != null) que.offer(node.left);
if (node.right != null) que.offer(node.right);
}
}
return min;
}
}
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/32"/><category term="算法"/><published>2023-05-18T15:42:21+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/31</id><title>LC 117. 填充每个节点的下一个右侧节点指针II</title><updated>2024-04-14T05:46:54.210517+00:00</updated><content type="html"><![CDATA[<h3>117. 填充每个节点的下一个右侧节点指针II</h3>
<blockquote>
<p>该题目和116的区别:就是116题是完全二叉树,这道题不是完全二叉树,题解完全一样的。<strong><code>略</code></strong></p>
</blockquote>
<h3>3.9 104. 二叉树的最大深度</h3>
<blockquote>
<p>思路:依旧是层序遍历,计算共有多少层即可</p>
</blockquote>
<pre><code class="language-java">class Solution {
public int maxDepth(TreeNode root) {
if (root == null) {
return 0;
}
Queue<TreeNode> que = new LinkedList<>();
que.offer(root);
int count = 0;//记录深度
while (!que.isEmpty()) {
int len = que.size();
count++;
for (int i = 0; i < len; i++) {
TreeNode node = que.poll();//弹出并记录
//放入节点的左右节点
if (node.left != null) que.offer(node.left);
if (node.right != null) que.offer(node.right);
}
}
return count;
}
}
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/31"/><category term="算法"/><published>2023-05-18T15:41:53+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/30</id><title>LC 116. 填充每个节点的下一个右侧节点指针</title><updated>2024-04-14T05:46:54.272082+00:00</updated><content type="html"><![CDATA[<h3>116. 填充每个节点的下一个右侧节点指针</h3>
<blockquote>
<p>思路:</p>
</blockquote>
<ul>
<li>层序遍历 一个while 一个for循环</li>
<li>处理for循环的时候,让<code>下标i小于数组最大下标</code>的每一层的每一个节点指向下一个节点的值(只是查看值,而不弹出,<strong>用peek()</strong>)</li>
</ul>
<pre><code class="language-java">/*
// Definition for a Node.
class Node {
public int val;
public Node left;
public Node right;
public Node next;
public Node() {}
public Node(int _val) {
val = _val;
}
public Node(int _val, Node _left, Node _right, Node _next) {
val = _val;
left = _left;
right = _right;
next = _next;
}
};
*/
class Solution {
public Node connect(Node root) {
if (root == null) {
return root;
}
Queue<Node> que = new LinkedList<>();
que.offer(root);
while (!que.isEmpty()) {
int len = que.size();//每一层的数量是会改变的,记录下来
for (int i = 0; i < len; i++) {
Node node = que.poll();
//连接每一层的节点,当该层的节点的数量大于1就可连接
if (i < len - 1) {
node.next = que.peek();//不弹出该节点,只是查看
}
//扩展下一层的节点放入队列中
if (node.left != null) que.offer(node.left);
if (node.right != null) que.offer(node.right);
}
}
return root;
}
}
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/30"/><category term="算法"/><published>2023-05-18T15:41:12+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/29</id><title>LC 515. 在每个树行中找最大值</title><updated>2024-04-14T05:46:54.334777+00:00</updated><content type="html"><![CDATA[<h3>515. 在每个树行中找最大值</h3>
<blockquote>
<p>思路:层序遍历,取每一层的最大值,放到一维数组,最后返回结果集</p>
</blockquote>
<pre><code class="language-java">Collections.emptyList()//这个方法返回的List是Collections类的一个静态内部类,它继承AbstractList后并没有实现add()、remove()等方法,因此这个返回值List并不能增加删除元素
</code></pre>
<ul>
<li>层序遍历</li>
<li>处理每一层的时候找到最大值即可</li>
</ul>
<blockquote>
<p>用到:</p>
</blockquote>
<pre><code class="language-java">class Solution {
public List<Integer> largestValues(TreeNode root) {
if (root == null) {
return Collections.emptyList();//直接返回空列表,减少开销
}
Queue<TreeNode> que = new LinkedList<>();//创建队列
List<Integer> res = new ArrayList<>();//结果集
que.offer(root);//根节点入队
while (!que.isEmpty()) {
int len = que.size();//记录当前节点的数量
int max = Integer.MIN_VALUE;//先赋予int类型的最小值
for (int i = 0; i < len; i++) {//找每一层的最大值
TreeNode node = que.poll();//从队列中取出元素
max = Math.max(max, node.val);//找出该层的最大值
//放入该节点的左右节点到队列
if (node.left != null) que.offer(node.left);
if (node.right != null) que.offer(node.right);
}
//将每一层的最大值放到结果集
res.add(max);
}
return res;
}
}
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/29"/><category term="算法"/><published>2023-05-18T15:38:38+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/28</id><title>N叉树的层序遍历</title><updated>2024-04-14T05:46:54.413245+00:00</updated><content type="html"><![CDATA[<h3>N叉树的层序遍历</h3>
<blockquote>
<p>思路:依然是层序遍历,只是<strong>节点的孩子有多个了</strong>,children也是List<Node>类型的,将节点的所有孩子遍历后全部放入队列即可:</p>
</blockquote>
<blockquote>
<p><strong>遍历方式</strong></p>
</blockquote>
<ul>
<li>增强for循环</li>
<li>普通for循环</li>
</ul>
<pre><code class="language-java">class Solution {
public List<List<Integer>> levelOrder(Node root) {
List<List<Integer>> result = new ArrayList<>();
Queue<Node> que = new LinkedList<>();
if (root != null) {
que.offer(root);
}
while (!que.isEmpty()) {
List<Integer> list = new ArrayList<>();
int len = que.size();
for (int i = 0; i < len; i++) {
Node node = que.poll();
list.add(node.val);//取出节点的值加入到结果集
//添加节点的孩子到队列,是Node类型的List
List<Node> children = node.children;
//遍历孩子,放到队列中
// for (int j = 0; j < children.size(); j++) {
// if (children.get(j) != null ) {
// que.offer(children.get(j));//将节点加入到队列
// }
// }
for (Node child : children) {
if (child != null) {
que.offer(child);
}
}
}
result.add(list);
}
return result;
}
}
</code></pre>
<p><strong>N叉树(节点)的定义</strong>:</p>
<pre><code class="language-java">// Definition for a Node.
class Node {
public int val;
public List<Node> children;//孩子也是节点类型的
public Node() {}//构造器
public Node(int _val) {//有参构造器
val = _val;
}
public Node(int _val, List<Node> _children) {//有参构造器
val = _val;
children = _children;
}
};
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/28"/><category term="算法"/><published>2023-05-18T15:38:00+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/27</id><title>LC 637. 二叉树的层平均值</title><updated>2024-04-14T05:46:54.485983+00:00</updated><content type="html"><![CDATA[<h3>637. 二叉树的层平均值</h3>
<p>思路:</p>
<ul>
<li>层次遍历的时候,每一层求一个总和</li>
<li>该层结束,就求这一层的平均值即可</li>
</ul>
<pre><code class="language-java">class Solution {
public List<Double> averageOfLevels(TreeNode root) {
Queue<TreeNode> que = new LinkedList<>();
//判断空
if (root != null) {
que.offer(root);
}
List<Double> list = new ArrayList<>();
while (!que.isEmpty()) {
int len = que.size();
double sum = 0.0;
for (int i = 0; i < len; i++) {//这里不能用while判断 会改变len的值
TreeNode node = que.poll();//弹出并临时记录
sum += node.val;//求和
//将该层的平均值存放到一维数组中
if (node.left != null) {
que.add(node.left);
}
if (node.right != null) {
que.add(node.right);
}
}
list.add(sum / len);
}
return list;
}
}
</code></pre>
<blockquote>
<p>注意:这里不能用while</p>
</blockquote>
<pre><code class="language-java">不能用 while(len > 0) {
...
len--;
}
因为len改变了,就无法计算sum/len了,这点要注意
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/27"/><category term="算法"/><published>2023-05-18T15:36:44+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/26</id><title>LC107. 二叉树的层次遍历</title><updated>2024-04-14T05:46:54.567733+00:00</updated><content type="html"><![CDATA[<h3>3.2 107. 二叉树的层次遍历</h3>
<pre><code class="language-java">class Solution {
public List<List<Integer>> levelOrderBottom(TreeNode root) {
/*思路:
1.广搜得到二维数组的结果
2.将二维数组反转
*/
//创建一个结果二维数组
List<List<Integer>> res = new ArrayList<>();
Queue<TreeNode> que = new LinkedList<>();
if (root == null) {
return res;
}
que.offer(root);//根节点放入队列
while (!que.isEmpty()) {
//创建一维数组保存当前层的节点
List<Integer> list = new ArrayList<>();
//保存当前层的节点的数量
int len = que.size();
for (int i = 0; i < len; i++) {
//保存当前出队的节点
TreeNode node = que.poll();
//将其值存入到一维数组
list.add(node.val);
//将该节点的左右节点入队
if (node.left != null) que.offer(node.left);//空节点不入队
if (node.right != null) que.offer(node.right);
}
//将该层的节点的值存放到一维数组中
res.add(list);
}
//开辟一个二维数组的空间,存放反转后的二维数组的结果
List<List<Integer>> result = new ArrayList<>();
for (int i = res.size() - 1; i >= 0; i--) {//数组下标从0开始,最大长度是数组大小减1
result.add(res.get(i));//get获取对应位置的元素
}
//返回结果
return result;
}
}
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/26"/><category term="算法"/><published>2023-05-18T15:36:11+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/25</id><title>LC 102.二叉树的层序遍历</title><updated>2024-04-14T05:46:54.629816+00:00</updated><content type="html"><![CDATA[<h3>102. 二叉树的层次遍历</h3>
<blockquote>
<p><strong>思路</strong>:</p>
</blockquote>
<ul>
<li>
<p><strong>定义数组和队列</strong>:将每一层的结果保存在一个一维数组中,将每一层的一维数组保存在二维数组中 <strong>判断队列是否为空</strong></p>
</li>
<li>
<p>遍历当前层,用size记录当前层的大小,控制当前遍历的次数</p>
</li>
<li>
<p>加入当前节点的下一层的左右孩子 </p>
</li>
<li>
<p>此时又重新获取了下一层的节点的数量</p>
</li>
</ul>
<pre><code class="language-java">/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public List<List<Integer>> levelOrder(TreeNode root) {
//创建一个二维数组 存放结果
List<List<Integer>> res = new ArrayList<>();
//创建一个队列
Queue<TreeNode> que = new LinkedList<TreeNode>();
//BFS广度优先搜索——使用队列实现
if (root != null) {
que.offer(root);
};
//广度优先搜索模板
/*如果不为空队列不为空,就创建一个数组,记录下队列的大小,将队列中的节点的值存入数组*/
while (!que.isEmpty()) {
//创建数组
List<Integer> list = new ArrayList<>();
//记录当前层数的节点个数 即当前层的队列的大小
int len = que.size();//队列的元素是会改变的
while (len > 0) {//只处理len个节点
//存放取出的节点
TreeNode node = que.poll();
list.add(node.val);//将节点的值放到数组中(一维数组)
//将该节点的左右节点都放到队列中 这样就改变了队列的节点的个数了
if (node.left != null) que.offer(node.left);
if (node.right != null) que.offer(node.right);
len--;
}
//将该层的节点(一维数组)放到二维数组里面
res.add(list);
}
return res;
}
}
</code></pre>
]]></content><link href="https://github.com/HealUP/MyBlog/issues/25"/><category term="算法"/><published>2023-05-18T15:33:22+00:00</published></entry><entry><id>https://github.com/HealUP/MyBlog/issues/24</id><title>剑指 Offer 29. 顺时针打印矩阵</title><updated>2024-04-14T05:46:54.715509+00:00</updated><content type="html"><![CDATA[<h3>[<a href="https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/">剑指 Offer 29. 顺时针打印矩阵</a>](https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/)</h3>
<p><strong>思路分析:根据题目示例 matrix = [[1,2,3],[4,5,6],[7,8,9]] 的对应</strong>输出 [1,2,3,6,9,8,7,4,5] 可以发现,顺时针打印矩阵的顺序是 “从左向右、从上向下、从右向左、从下向上” 循环。</p>
<p><a href="https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/solution/mian-shi-ti-29-shun-shi-zhen-da-yin-ju-zhen-she-d">https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/solution/mian-shi-ti-29-shun-shi-zhen-da-yin-ju-zhen-she-d</a></p>
<pre><code class="language-java">class Solution {
public int[] spiralOrder(int[][] matrix) {
if (matrix.length == 0) return new int [0];//矩阵为空,返回空数组即可
int l = 0, r = matrix[0].length-1, t = 0, b = matrix.length - 1, x = 0;//r 是列长度,即宽度b是行长度,即高度
int[] res = new int[(r + 1) * (b + 1)];//数组的大小就是二维数组相乘的大小
while (true) {
//left to right
for (int i = l; i <= r; i++) {
res[x++] = matrix[t][i];
}
//top大于bottom出边界了
if(++t > b) {
break;
}
//top to bottom
for (int i = t; i <= b; i++) {
res[x++] = matrix[i][r];
}
if (--r < l) {
break;
}
//right to left
for (int i = r; i >= l; i--) {
res[x++] = matrix[b][i];
}
if (--b <t) {
break;