1
- - [ 1 归并排序、随机快排] ( #1---------- )
2
- * [ 1.1 归并排序] ( #11----- )
3
- + [ 1.1.1 递归思路:] ( #111------ )
4
- + [ 1.1.2 非递归思路] ( #112------ )
5
- + [ 1.1.3 归并排序时间复杂度] ( #113---------- )
6
- + [ 1.1.4 归并面试题] ( #114------ )
7
- * [ 1.2 快排] ( #12--- )
8
- + [ 1.2.1 Partion过程] ( #121-partion-- )
9
- + [ 1.2.2 快排1.0:每次partion搞定一个位置] ( #122---10---partion------ )
10
- + [ 1.2.3 快排2.0:每次partion搞定一批位置] ( #123---20---partion------ )
11
- + [ 1.2.4 快排3.0:随机位置作为num标记位] ( #124---30-------num--- )
12
- + [ 1.2.5 快排的时间复杂度与空间复杂度] ( #125--------------- )
13
-
14
- # 1 归并排序、随机快排
15
-
16
- ## 1.1 归并排序
1
+ - [ 1 归并排序、随机快排] ( #1 )
2
+ * [ 1.1 归并排序] ( #11 )
3
+ + [ 1.1.1 递归思路:] ( #111 )
4
+ + [ 1.1.2 非递归思路] ( #112 )
5
+ + [ 1.1.3 归并排序时间复杂度] ( #113 )
6
+ + [ 1.1.4 归并面试题] ( #114 )
7
+ * [ 1.2 快排] ( #12 )
8
+ + [ 1.2.1 Partion过程] ( #121 )
9
+ + [ 1.2.2 快排1.0:每次partion搞定一个位置] ( #122 )
10
+ + [ 1.2.3 快排2.0:每次partion搞定一批位置] ( #123 )
11
+ + [ 1.2.4 快排3.0:随机位置作为num标记位] ( #124 )
12
+ + [ 1.2.5 快排的时间复杂度与空间复杂度] ( #125 )
13
+
14
+ < h1 id = ' 1 ' >1 归并排序、随机快排</ h1 >>
15
+
16
+ < h2 id = ' 11 ' > 1.1 归并排序</ h2 >>
17
17
18
18
1、 整体是递归的,左边排好序右边排好序,最后merge让整体有序,merge过程需要申请和被排序数组等长度的辅助空间
19
19
23
23
24
24
4、 归并排序可改为非递归实现
25
25
26
- ### 1.1.1 递归思路:
26
+ < h3 id = ' 111 ' > 1.1.1 递归思路:</ h3 >>
27
27
28
28
> 主函数希望一个数组的0~ 3位置排序f(arr, 0, 3)
29
29
35
35
36
36
> f(arr, 0, 3)需要merge f(arr, 0, 1)和f(arr, 2, 3)此时f(arr, 0, 1)和f(arr, 2, 3)已经有序merge后copy到原数组的0到3位置。于是f(arr, 0, 3)整体有序
37
37
38
- ### 1.1.2 非递归思路
38
+ < h3 id = ' 112 ' > 1.1.2 非递归思路</ h3 >>
39
39
40
40
> 对于一个给定长度为n的数组arr,我们希望arr有序
41
41
@@ -209,7 +209,7 @@ public class Code01_MergeSort {
209
209
}
210
210
```
211
211
212
- ### 1.1.3 归并排序时间复杂度
212
+ < h3 id = ' 113 ' > 1.1.3 归并排序时间复杂度</ h3 >>
213
213
214
214
> 递归复杂度计算,用master公式带入,子问题规模N/2,调用2次,除了递归之外的时间复杂度为merge的时间复杂度,为O(N)。a=2,b=2,d=1满足master第一条logb^a == d规则
215
215
@@ -223,7 +223,7 @@ T(N) = 2T(N/2) + O(N) => O(N*logN)
223
223
224
224
Tips: 为什么选择,冒泡,插入排序的时间复杂度为O(N^2)而归并排序时间复杂度为O(NlogN),因为选择,冒泡,插入排序的每个元素浪费了大量的比较行为N次。而归并没有浪费比较行为,每次比较的结果有序后都会保存下来,最终merge
225
225
226
- ### 1.1.4 归并面试题
226
+ < h3 id = ' 114 ' > 1.1.4 归并面试题</ h3 >>
227
227
228
228
1、在一个数组中,一个数左边比它小的数的总和,叫做小和,所有数的小和累加起来,叫做数组的小和。求数组的小和。例如[ 1, 3, 4, 2, 5]
229
229
@@ -389,9 +389,9 @@ public class Code02_SmallSum {
389
389
390
390
> 什么样的题目以后可以借助归并排序:纠结每个数右边(左边)有多少个数比自身大,比自身小等。求这种数的数量等等
391
391
392
- ## 1.2 快排
392
+ < h2 id = ' 12 ' > 1.2 快排</ h2 >>
393
393
394
- ### 1.2.1 Partion过程
394
+ < h3 id = ' 121 ' > 1.2.1 Partion过程</ h3 >>
395
395
396
396
> 给定一个数组arr,和一个整数num。请把小于等于num的数放在数组的左边,大于num的数放在数组的右边(不要求有序)。要求额外空间复杂度为O(1),时间复杂度为O(N)。例如[ 5,3,7,2,3,4,1] ,num=3,把小于等于3的放在左边,大于3的放在右边
397
397
@@ -413,18 +413,18 @@ public class Code02_SmallSum {
413
413
414
414
4、i和大于区域的边界相遇,停止操作
415
415
416
- ### 1.2.2 快排1.0:每次partion搞定一个位置
416
+ < h3 id = ' 122 ' > 1.2.2 快排1.0:每次partion搞定一个位置</ h3 >>
417
417
418
418
思路:在给定数组上做partion,选定数组最右侧的位置上的数作为num,小于num的放在该数组的左边,大于num的放在该数组的右边。完成之后,把该数组最右侧的数组num,交换到大于num区域的第一个位置,确保了交换后的num是小于等于区域的最后一个数(该数直至最后可以保持当前位置不变,属于已经排好序的数),把该num左侧和右侧的数分别进行同样的partion操作(递归)。相当于每次partion搞定一个数的位置,代码实现quickSort1
419
419
420
420
421
- ### 1.2.3 快排2.0:每次partion搞定一批位置
421
+ < h3 id = ' 123 ' > 1.2.3 快排2.0:每次partion搞定一批位置</ h3 >>
422
422
423
423
思路:借助荷兰国旗问题的思路,把arr进行partion,把小于num的数放左边,等于放中间,大于放右边。递归时把小于num的区域和大于num的区域做递归,等于num的区域不做处理。相当于每次partion搞定一批数,与标记为相等的数。代码实现quickSort2
424
424
425
425
> 第一版和第二版的快排时间复杂度相同O(N^2):用最差情况来评估,本身有序,每次partion只搞定了一个数是自身,进行了N次partion
426
426
427
- ### 1.2.4 快排3.0:随机位置作为num标记位
427
+ < h3 id = ' 124 ' > 1.2.4 快排3.0:随机位置作为num标记位</ h3 >>
428
428
429
429
==随机选一个位置i,让arr[ i] 和arr[ R] 交换,再用=arr[ R] 作为标记位。剩下的所有过程跟快排2.0一样。即为最经典的快排,时间复杂度为O(NlogN)==
430
430
@@ -438,7 +438,7 @@ T(N) = T((1/3)N) + T((2/3)N) + O(N)
438
438
439
439
> 对于这个递归表达式,master公式是解不了的,master公式只能解决子问题规模一样的递归。对于这个递归,算法导论上给出了计算方法,大致思路为假设一个复杂度,看这个公式是否收敛于这个复杂度的方式,比较麻烦
440
440
441
- ### 1.2.5 快排的时间复杂度与空间复杂度
441
+ < h3 id = ' 125 ' > 1.2.5 快排的时间复杂度与空间复杂度</ h3 >>
442
442
443
443
> 时间复杂度参考上文每种的复杂度
444
444
0 commit comments