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 >>
1717
18181、 整体是递归的,左边排好序右边排好序,最后merge让整体有序,merge过程需要申请和被排序数组等长度的辅助空间
1919
2323
24244、 归并排序可改为非递归实现
2525
26- ### 1.1.1 递归思路:
26+ < h3 id = ' 111 ' > 1.1.1 递归思路:</ h3 >>
2727
2828> 主函数希望一个数组的0~ 3位置排序f(arr, 0, 3)
2929
3535
3636> 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)整体有序
3737
38- ### 1.1.2 非递归思路
38+ < h3 id = ' 112 ' > 1.1.2 非递归思路</ h3 >>
3939
4040> 对于一个给定长度为n的数组arr,我们希望arr有序
4141
@@ -209,7 +209,7 @@ public class Code01_MergeSort {
209209}
210210```
211211
212- ### 1.1.3 归并排序时间复杂度
212+ < h3 id = ' 113 ' > 1.1.3 归并排序时间复杂度</ h3 >>
213213
214214> 递归复杂度计算,用master公式带入,子问题规模N/2,调用2次,除了递归之外的时间复杂度为merge的时间复杂度,为O(N)。a=2,b=2,d=1满足master第一条logb^a == d规则
215215
@@ -223,7 +223,7 @@ T(N) = 2T(N/2) + O(N) => O(N*logN)
223223
224224Tips: 为什么选择,冒泡,插入排序的时间复杂度为O(N^2)而归并排序时间复杂度为O(NlogN),因为选择,冒泡,插入排序的每个元素浪费了大量的比较行为N次。而归并没有浪费比较行为,每次比较的结果有序后都会保存下来,最终merge
225225
226- ### 1.1.4 归并面试题
226+ < h3 id = ' 114 ' > 1.1.4 归并面试题</ h3 >>
227227
2282281、在一个数组中,一个数左边比它小的数的总和,叫做小和,所有数的小和累加起来,叫做数组的小和。求数组的小和。例如[ 1, 3, 4, 2, 5]
229229
@@ -389,9 +389,9 @@ public class Code02_SmallSum {
389389
390390> 什么样的题目以后可以借助归并排序:纠结每个数右边(左边)有多少个数比自身大,比自身小等。求这种数的数量等等
391391
392- ## 1.2 快排
392+ < h2 id = ' 12 ' > 1.2 快排</ h2 >>
393393
394- ### 1.2.1 Partion过程
394+ < h3 id = ' 121 ' > 1.2.1 Partion过程</ h3 >>
395395
396396> 给定一个数组arr,和一个整数num。请把小于等于num的数放在数组的左边,大于num的数放在数组的右边(不要求有序)。要求额外空间复杂度为O(1),时间复杂度为O(N)。例如[ 5,3,7,2,3,4,1] ,num=3,把小于等于3的放在左边,大于3的放在右边
397397
@@ -413,18 +413,18 @@ public class Code02_SmallSum {
413413
4144144、i和大于区域的边界相遇,停止操作
415415
416- ### 1.2.2 快排1.0:每次partion搞定一个位置
416+ < h3 id = ' 122 ' > 1.2.2 快排1.0:每次partion搞定一个位置</ h3 >>
417417
418418思路:在给定数组上做partion,选定数组最右侧的位置上的数作为num,小于num的放在该数组的左边,大于num的放在该数组的右边。完成之后,把该数组最右侧的数组num,交换到大于num区域的第一个位置,确保了交换后的num是小于等于区域的最后一个数(该数直至最后可以保持当前位置不变,属于已经排好序的数),把该num左侧和右侧的数分别进行同样的partion操作(递归)。相当于每次partion搞定一个数的位置,代码实现quickSort1
419419
420420
421- ### 1.2.3 快排2.0:每次partion搞定一批位置
421+ < h3 id = ' 123 ' > 1.2.3 快排2.0:每次partion搞定一批位置</ h3 >>
422422
423423思路:借助荷兰国旗问题的思路,把arr进行partion,把小于num的数放左边,等于放中间,大于放右边。递归时把小于num的区域和大于num的区域做递归,等于num的区域不做处理。相当于每次partion搞定一批数,与标记为相等的数。代码实现quickSort2
424424
425425> 第一版和第二版的快排时间复杂度相同O(N^2):用最差情况来评估,本身有序,每次partion只搞定了一个数是自身,进行了N次partion
426426
427- ### 1.2.4 快排3.0:随机位置作为num标记位
427+ < h3 id = ' 124 ' > 1.2.4 快排3.0:随机位置作为num标记位</ h3 >>
428428
429429==随机选一个位置i,让arr[ i] 和arr[ R] 交换,再用=arr[ R] 作为标记位。剩下的所有过程跟快排2.0一样。即为最经典的快排,时间复杂度为O(NlogN)==
430430
@@ -438,7 +438,7 @@ T(N) = T((1/3)N) + T((2/3)N) + O(N)
438438
439439> 对于这个递归表达式,master公式是解不了的,master公式只能解决子问题规模一样的递归。对于这个递归,算法导论上给出了计算方法,大致思路为假设一个复杂度,看这个公式是否收敛于这个复杂度的方式,比较麻烦
440440
441- ### 1.2.5 快排的时间复杂度与空间复杂度
441+ < h3 id = ' 125 ' > 1.2.5 快排的时间复杂度与空间复杂度</ h3 >>
442442
443443> 时间复杂度参考上文每种的复杂度
444444
0 commit comments