为了笔试面试学习快排,但总是学了忘 忘了学,干脆做个笔记,方便以后回忆
基本思想:快速排序使用分而治之的策略来把一个序列分为较小和较大的 2 个子序列,然后递归地排序两个子序列
算法流程:
- 挑选基准值:从数列中挑出一个元素,称为“基准”(pivot);
- 分割(partition):重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(与基准值相等的数可以到任何一边)。在这个分割结束之后,对基准值的排序就已经完成;
- 递归排序子序列:递归地将小于基准值元素的子序列和大于基准值元素的子序列快速排序。
递归到最底部的判断条件是数列的大小是零或一,此时该数列显然已经有序。
具体实现的一种方式:
- 以(子)数组最左端元素为pivot;
- 每次先从右侧(以 right 指代)开始找到小于pivot的元素,并记录这个元素的索引位置j,再从左侧(以 left 指代)开始找到大于等于pivot的元素,并记录这个元素的索引位置i;
- 接着交换索引位置i,j对应的元素值
- 当左右指针相遇时,将pivot放置于 left/right 处,此时得到了一个有效的分割:小于pivot的元素均在其左侧,大于pivot的元素均在其右侧(等于pivot的元素可放置于任何一边);
- 对pivot两侧的子数组递归排序,直至子数组无法再分割。
这个实现的过程,可以看成是对数组的中序遍历。即先处理当前“节点”,再左右递归。
def sortArray(nums: List[int]) -> List[int]:
n = len(nums)
def quick(left, right):
if left >= right:
return nums
pivot = left
i = left
j = right
while i < j:
while i < j and nums[j] > nums[pivot]:
j -= 1
while i < j and nums[i] <= nums[pivot]:
i += 1
nums[i], nums[j] = nums[j], nums[i]
nums[pivot], nums[j] = nums[j], nums[pivot]
quick(left, j - 1)
quick(j + 1, right)
return nums
return quick(0, n - 1)