快速排序
一个引入例子
- 荷兰国旗问题
- 荷兰国旗问题就是指,给定一个目标数
target
和目标数组array
,设计一个方法,使得该数组中大于target
的数都放在左边,小于target
的数都放在右边,等于target
的数都放在中间. - 步骤:
- 设计一个左边界,使其初始位置在下标
0
的左边一位. - 设计一个右边界,使其初始位置在最后一个元素下标的的右边一位即
array.length
. - 给定一个计数变量
cur
,记录当前数组中第几个数在被操作比较. - 如果
array[cur] > target
,则左边界的下一位数和当前位置的数交换,同时左边界移动到下标为1的位置,即左边界++右移一位
,以及当前位置下移一位. - 如果
array[cur] < target
,则右边界的前一位数和当前位置的数交换,同时右边界下标为array.length - 1
的位置,即右边界--左移一位
,注意,此时当前位置不移动,因为交换过来的数没有进行判断. - 如果
array[cur] == target
,不坐任何操作,当前位置++.
- 设计一个左边界,使其初始位置在下标
- 这个代码其实很简单,可能我说不是很好理解,我直接贴代码: 荷兰国旗问题代码.
- 其时间复杂度为
o(N)
,额外空间复杂度为O(1)
.
- 荷兰国旗问题就是指,给定一个目标数
根据荷兰国旗问题的快速排序
-
快速排序怎么排?
- 给定一个数组
[1,2,3,4,5,4,3]
,然后把数组的最后一个数1
作为比较的数. - 和最后一个数
1
相比,跟荷兰国旗一样,小的放左边,大的放右边,等于的放中间. - 然后再去对小于区和大于区这样做
- …如此循环下来,数组就有序了.
- 快速排序代码.
- 这种快排别经典快排要快一些,经典快排一次只排一个数,而这种一次可以把相等的都放好,反正我学了这种我就把经典快排忘了哈哈哈.
- 给定一个数组
-
它的时间复杂度:
- 当已经有序的来排序的时候,例如
[1,2,3,4,5,6]
,来排序的时候,每次都用最后一个去比较,每次都只能排序一个,这样子的左右部分规模差别很大的时候,时间复杂度为O(N^2)
. - 最好的情况是,每次左边界和右边界的数都差不多相等,然后就是一个递归的过程,时间复杂度就和归并一样了,为
O(N*logN)
. - 这就是经典快排的缺点,和数据的状况有一定关系.
- 当已经有序的来排序的时候,例如
随机快排
- 随机快排就是指在给定排序的数组中随机选择一个数去作为本次的
参照数
,虽然这样子还是有可能出现左右部分的规模差别很大,不过这个就是概率问题了,所以这样的快排时间复杂度就只能用平均时间复杂度,也就是我们的期望值来表示. - 这个时间复杂度就记住就可以了,反正我不会证明,数学不好,随机快排期望时间复杂度为: O(N*logN).
- 随机快排相较于上面的快排就只多了一行代码,这行代码使得我们随机找出来一个数作为最后一个数,也就是参照数哈哈哈,我在代码里标注出来了,代码: 随机快排代码.