面试官问:为什么快排要随机化?

十大排序算法里面,快排(Quick Sort)算得上是我们最熟悉的一类,可一旦问下面的问题,很多人或许一下子会卡壳。

快排的核心是什么?
为什么 pivot 需要随机化?
如果不随机,会咋样?
你现场能手写吗?

这些问题核心点就是考察是不是真的理解“快排为什么能快”

一、故事从「冒泡排序」开始讲

假设我们手里有一叠无序的书,需要整理。

第一反应是什么?

“小的往前放,大的往后放”

这就是冒泡的思想。

但效率很低,平均 O(n²)。

那有没有更聪明点的办法?

二、快排的本质:分治

快排的精髓只有一句话:

找一个基准(pivot),把比它小的放左边,比它大的放右边。

再对两边递归处理。

这样就能一点点把区间缩小,不断排干净。

形象地说:

我不一次性全排
我只负责“把该在左边的放左边”
剩下的递给你自己解决

这叫 分治(Divide and Conquer)

三、那为什么快排能“快”?

公式很经典:

平均时间复杂度:O(n log n)
最坏时间复杂度:O(n²)

关键就在选的 pivot

  • 如果 pivot 选得好 → 每次都能“对半分” → log n 层递归

  • 如果 pivot 选得差 → 每次只分出一个元素 → 变成冒泡 → O(n²)

那么问题来了:pivot 到底怎么选?

四、如果不随机,会发生什么?

有些人会写成:

pivot = nums[0]

听起来没毛病,但在真实的数据中:

  • 如果数组本身接近有序

  • pivot 永远在最边上

  • 每次只能排掉一个元素

  • 复杂度直接从 O(n log n) 退化成 O(n²)

这就是为什么:

写快排不用随机化,就是等着被面试官针对。

因为真实业务场景中,「接近有序的数据」非常常见。

例如:日志时间戳、价格序列、用户行为轨迹……

也就是说:

不随机,快排很可能不“快”。

五、那怎么解决?

随机化!

随机化的 pivot 选择很简单:

import random

pivot_index = random.randint(left, right)
nums[left], nums[pivot_index] = nums[pivot_index], nums[left]

通过随机扰动,让 pivot 的位置不可预测

  • 能够避免“极端接近有序场景”

  • 使得快排的 期望时间复杂度稳定为 O(n log n)

这是工程上真实会用到的所谓 反击退化风险 的手段。

六、现场手写一个?

那我们就写一个 可过所有在线评测的标准解法

def quick_sort(nums, left, right):
    if left >= right:
        return

    # 随机化 pivot
    import random
    pivot_idx = random.randint(left, right)
    nums[left], nums[pivot_idx] = nums[pivot_idx], nums[left]
    pivot = nums[left]

    i, j = left, right
    while i < j:
        # 右边先走,找比 pivot 小的
        while i < j and nums[j] >= pivot:
            j -= 1
        # 左边再走,找比 pivot 大的
        while i < j and nums[i] <= pivot:
            i += 1
        nums[i], nums[j] = nums[j], nums[i]

    # pivot 放回中间
    nums[left], nums[i] = nums[i], nums[left]

    quick_sort(nums, left, i - 1)
    quick_sort(nums, i + 1, right)

这段代码面试现场可以直接写,不翻车。

七、总结面试时怎么答得漂亮

可以这样说:

“快排的核心是分治,通过 pivot 将数组划分成左右两部分再递归。

如果 pivot 选择不当,比如数据接近有序,会退化成 O(n²)。

为避免退化,我们会采用随机化 pivot,让每次划分更均匀,使时间复杂度稳定在 O(n log n)。

然后你需要我现场手写的话,我可以写标准版 + 随机化版本。”

这叫在理解的基础上 会写 + 会解释 + 会设计

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值