@@ -282,42 +282,42 @@ func sumMerge(arr []int, L, M, R int) int {
282282
2832832、 arr[ i] > num, 不做操作,i++
284284
285- > 给定一个数组,和一个整数num。请把小于num的数放在数组的左边,等于num的放中间,大于num的放右边。要求额外空间复杂度为O(1),时间复杂度为O(N)。[ 3,5,4,0,4,6,7,2] ,num=4。实质是经典荷兰国旗问题
285+ > 给定一个数组,和一个整数num。请把小于num的数放在数组的左边,等于num的放中间,大于num的放右边。要求额外空间复杂度为O(1),时间复杂度为O(N)。[ 3,5,4,0,4,6,7,2] ,num=4。该问题实质就是经典的荷兰国旗问题
286286
287- 思路:设计一个小于区域,下标为-1。设计一个大于区域,下表为arr.length,越界位置 。
287+ 思路:设计一个小于区域,下标为-1。设计一个大于区域,下表为arr.length, 数组的左右越界位置 。
288288
289- 1、 如果arr[ i] 当前位置的数==num , i++直接跳下一个
289+ 1、 如果arr[ i] 等于当前位置的数num , i++直接跳下一个。间接的扩大了等于区域
290290
291- 2、 如果arr[ i] 当前位置的数< num ,当前位置的数arr[ i] 和小于区域的右一个交换,小于区域右扩一个位置,当前位置i++
291+ 2、 如果arr[ i] 当前位置的数小于num ,当前位置的数arr[ i] 和小于区域的右一个交换,小于区域右扩一个位置,当前位置i++
292292
293- 3、 如果arr[ i] 当前位置的数> num ,当前位置的数arr[ i] 与大于区域的左边一个交换,大于区域左移一个位置,i停在原地不做处理,这里不做处理是因为当前位置的数是刚从大于区域交换过来的数,还没做比较
293+ 3、 如果arr[ i] 当前位置的数大于num ,当前位置的数arr[ i] 与大于区域的左边一个交换,大于区域左移一个位置,i停在原地不做处理,这里不做处理是因为当前位置的数是刚从大于区域交换过来的数,还没做比较
294294
295- 4、i和大于区域的边界相遇 ,停止操作
295+ 4、当i和大于区域的边界相遇 ,停止操作
296296
297297### 1.2.2 快排1.0:每次partion搞定一个位置
298298
299- 思路:在给定数组上做partion,选定数组最右侧的位置上的数作为num,小于num的放在该数组的左边,大于num的放在该数组的右边。完成之后,把该数组最右侧的数组num,交换到大于num区域的第一个位置,确保了交换后的num是小于等于区域的最后一个数(该数直至最后可以保持当前位置不变,属于已经排好序的数),把该num左侧和右侧的数分别进行同样的partion操作(递归)。相当于每次partion搞定一个数的位置,代码实现quickSort1
299+ 思路:在给定数组上做partion, 选定数组最右侧的位置上的数作为num,小于num的放在该数组的左边,大于num的放在该数组的右边。完成之后,把该数组最右侧的数组num,交换到大于num区域的第一个位置,确保了交换后的num是小于等于区域的最后一个数(该数直至最后可以保持当前位置不变,属于已经排好序的数),把该num左侧和右侧的数分别进行同样的partion操作(递归)。相当于每次partion搞定一个数的位置,代码实现quickSort1
300300
301301
302302### 1.2.3 快排2.0:每次partion搞定一批位置
303303
304- 思路:借助荷兰国旗问题的思路,把arr进行partion,把小于num的数放左边,等于放中间,大于放右边。递归时把小于num的区域和大于num的区域做递归,等于num的区域不做处理。相当于每次partion搞定一批数,与标记为相等的数 。代码实现quickSort2
304+ 思路:借助荷兰国旗问题的思路,把arr进行partion,把小于num的数放左边,等于放中间,大于放右边。递归时把小于num的区域和大于num的区域做递归,等于num的区域不做处理。相当于每次partion搞定一批数,该批数都与标记数相等 。代码实现quickSort2
305305
306306> 第一版和第二版的快排时间复杂度相同O(N^2):用最差情况来评估,本身有序,每次partion只搞定了一个数是自身,进行了N次partion
307307
308308### 1.2.4 快排3.0:随机位置作为num标记位
309309
310- == 随机选一个位置i,让arr[ i] 和arr[ R] 交换,再用=arr [ R] 作为标记位 。剩下的所有过程跟快排2.0一样。即为最经典的快排,时间复杂度为O(NlogN)==
310+ > 随机选一个位置i,让arr[ i] 和arr[ R] 交换,再选取arr [ R] 的值作为标记位 。剩下的所有过程跟快排2.0一样。即为最经典的快排,时间复杂度为O(NlogN)
311311
312- > 为什么随机选择标记为时间复杂度就由O (N^2)变为O(NlogN)? 如果我们随机选择位置那么就趋向于标记位的左右两侧的递归规模趋向于N/2。那么根据master公式,可以计算出算法复杂度为O(NlogN)。实质上,在我们选择随机的num时,最差情况,最好情况,其他各种情况的出现概率为1/N。对于这N种情况,数学上算出的时间复杂度最终期望是O(NlogN),这个数学上可以进行证明,比较复杂
312+ > 为什么随机选择标记位的时间复杂度由原本不随机的O (N^2)变为O(NlogN)了呢? 如果我们随机选择位置那么就趋向于标记位的左右两侧的递归规模趋向于N/2。那么根据master公式,可以计算出算法复杂度为O(NlogN)。实质上,在我们选择随机的num时,最差情况,最好情况,其他各种情况的出现概率为1/N。对于这N种情况,数学上算出的时间复杂度最终期望是O(NlogN),这个数学上可以进行证明,证明相对较复杂
313313
314314> 例如我们的num随机到数组左侧三分之一的位置,那么master公式为
315315
316316``` math
317317T(N) = T((1/3)N) + T((2/3)N) + O(N)
318318```
319319
320- > 对于这个递归表达式,master公式是解不了的,master公式只能解决子问题规模一样的递归。对于这个递归,算法导论上给出了计算方法,大致思路为假设一个复杂度,看这个公式是否收敛于这个复杂度的方式,比较麻烦
320+ > 对于这个递归表达式,master公式是解不了的,master公式只能解决子问题规模一样的递归。对于这个递归,算法导论上给出了计算方法,大致思路为假设一个复杂度,看这个公式是否收敛于这个复杂度的方式
321321
322322### 1.2.5 快排的时间复杂度与空间复杂度
323323
0 commit comments