题目描述
思路解析动画文字版
记住三个角色:pivot 基准(橙)、边界 i(小区右端)、扫描指针 j。小于基准就「换进小区」,否则跳过。
本轮处理下标 0~6 这一段。基准 pivot = 最右的 4(橙色)。边界 i 先停在 -1(小区还空着),指针 j 从下标 0 开始往右扫。
指针 j 走到下标 0,值是 5。和基准 4 比一比:5 不小于 4,留在原地、j 直接跳过。
指针 j 走到下标 1,值是 2。和基准 4 比一比:2 小于 4,要换进左边小区。
2 小于基准:边界 i 前进到 0,把下标 0 和下标 1 的数交换,2 进了左边小区,原来 0 处的数被换到了 1。
指针 j 走到下标 2,值是 7。和基准 4 比一比:7 不小于 4,留在原地、j 直接跳过。
指针 j 走到下标 3,值是 3。和基准 4 比一比:3 小于 4,要换进左边小区。
3 小于基准:边界 i 前进到 1,把下标 1 和下标 3 的数交换,3 进了左边小区,原来 1 处的数被换到了 3。
指针 j 走到下标 4,值是 1。和基准 4 比一比:1 小于 4,要换进左边小区。
1 小于基准:边界 i 前进到 2,把下标 2 和下标 4 的数交换,1 进了左边小区,原来 2 处的数被换到了 4。
指针 j 走到下标 5,值是 6。和基准 4 比一比:6 不小于 4,留在原地、j 直接跳过。
扫描结束。把基准 4 换到边界后一格(下标 3):原来 3 处的数被换到了最右。现在 4 左边全比它小、右边全比它大。
基准 4 标绿——它已经在最终位置,永远不再动。接下来分别对它左边 [0~2] 和右边 [4~6] 两段重复同样的分区。
本轮处理下标 0~2 这一段。基准 pivot = 最右的 1(橙色)。边界 i 先停在 -1(小区还空着),指针 j 从下标 0 开始往右扫。
指针 j 走到下标 0,值是 2。和基准 1 比一比:2 不小于 1,留在原地、j 直接跳过。
指针 j 走到下标 1,值是 3。和基准 1 比一比:3 不小于 1,留在原地、j 直接跳过。
扫描结束。把基准 1 换到边界后一格(下标 0):原来 0 处的数被换到了最右。现在 1 左边全比它小、右边全比它大。
基准 1 标绿——它已经在最终位置,永远不再动。接下来分别对它左边 [0~-1] 和右边 [1~2] 两段重复同样的分区。
本轮处理下标 1~2 这一段。基准 pivot = 最右的 2(橙色)。边界 i 先停在 0(小区还空着),指针 j 从下标 1 开始往右扫。
指针 j 走到下标 1,值是 3。和基准 2 比一比:3 不小于 2,留在原地、j 直接跳过。
扫描结束。把基准 2 换到边界后一格(下标 1):原来 1 处的数被换到了最右。现在 2 左边全比它小、右边全比它大。
基准 2 标绿——它已经在最终位置,永远不再动。接下来分别对它左边 [1~0] 和右边 [2~2] 两段重复同样的分区。
本轮处理下标 4~6 这一段。基准 pivot = 最右的 5(橙色)。边界 i 先停在 3(小区还空着),指针 j 从下标 4 开始往右扫。
指针 j 走到下标 4,值是 7。和基准 5 比一比:7 不小于 5,留在原地、j 直接跳过。
指针 j 走到下标 5,值是 6。和基准 5 比一比:6 不小于 5,留在原地、j 直接跳过。
扫描结束。把基准 5 换到边界后一格(下标 4):原来 4 处的数被换到了最右。现在 5 左边全比它小、右边全比它大。
基准 5 标绿——它已经在最终位置,永远不再动。接下来分别对它左边 [4~3] 和右边 [5~6] 两段重复同样的分区。
本轮处理下标 5~6 这一段。基准 pivot = 最右的 7(橙色)。边界 i 先停在 4(小区还空着),指针 j 从下标 5 开始往右扫。
指针 j 走到下标 5,值是 6。和基准 7 比一比:6 小于 7,要换进左边小区。
6 小于基准:边界 i 前进到 5,正好是它自己,原地不动。小区右端推进到下标 5。
扫描结束,边界后一格正好就是基准所在的下标 6,基准 7 不用换、已经归位。
基准 7 标绿——它已经在最终位置,永远不再动。接下来分别对它左边 [5~5] 和右边 [7~6] 两段重复同样的分区。
所有基准都归了位,每个数左边都比它小、右边都比它大——数组已经从小到大排好:[1,2,3,4,5,6,7]。
三个高频追问:复杂度的来由、稳定性、以及和归并的取舍。
参考代码
def quicksort(a, lo, hi): if lo >= hi: return # 段内 ≤1 个数,天然有序 piv = a[hi] # 基准取最右 i = lo - 1 # 小区右端 for j in range(lo, hi): # j 扫到基准前一格 if a[j] < piv: # 小于基准:换进小区 i += 1 a[i], a[j] = a[j], a[i] a[i+1], a[hi] = a[hi], a[i+1] # 基准归位 quicksort(a, lo, i) # 递归排左段 quicksort(a, i+2, hi) # 递归排右段复杂度
- 时间(平均):O(n log n),每层分区把数组分成两半,约 log n 层,每层合计扫 n 个元素
- 时间(最坏):O(n²),基准每次都选到最大或最小(如已排好序),分区极度失衡退化成 n 层
- 空间:O(log n),原地交换不开新数组,额外开销只在递归栈的深度
易错点
面试追问把动画讲成自己的话
追问快排为什么平均是 O(n log n),最坏是 O(n²)?
追问快排是稳定排序吗?
追问快排和归并排序怎么选?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
归并排序
中等 · 沿着 排序套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题