以下是快速排序与归并排序详解,结合通俗例子和核心考点,助你高效掌握关键概念。
⚡ 一、快速排序(Quick Sort)
1. 核心思想
- 分治策略:选一个基准值(pivot),将数组分为两部分——左侧全≤基准值,右侧全>基准值,递归处理子数组。
- 通俗例子:
假设超市结账排队,选一人身高1.7m为基准,比他矮的站左边,高的站右边。接着左右两队各自重复此操作,直到全员有序。
2. 代码实现(Python)
import random
def quick_sort(arr, l, r):
if l >= r: return
# 优化:随机选基准避免最坏情况
pivot_idx = random.randint(l, r)
arr[l], arr[pivot_idx] = arr[pivot_idx], arr[l]
pivot = arr[l]
i, j = l, r
while i < j:
while i < j and arr[j] >= pivot: j -= 1 # 右找小值
while i < j and arr[i] <= pivot: i += 1 # 左找大值
if i < j: arr[i], arr[j] = arr[j], arr[i]
arr[l], arr[i] = arr[i], arr[l] # 基准归位
quick_sort(arr, l, i-1)
quick_sort(arr, i+1, r)
3. 性能分析
指标 | 详情 |
---|---|
时间复杂度 | 平均:O(n log n);最坏(有序数组):O(n²) |
空间复杂度 | 递归栈深度,平均O(log n) |
稳定性 | ❌ 不稳定(交换可能破坏相等元素顺序) |
4. 面试优化点
- 随机基准:避免有序数组导致分区失衡。
- 三数取中:选左、中、右的中位数作基准,进一步优化分区。
- 小规模转插入排序:当子数组<10时,插入排序更高效(因常数因子小)。
🔄 二、归并排序(Merge Sort)
1. 核心思想
- 分治+合并:数组二分至单元素(天然有序),再两两合并成有序大数组。
- 通俗例子:
整理扑克牌:先分成两堆分别排序,再将两堆牌按大小合并。合并时比较两堆顶部的牌,取小者放入新堆。
2. 代码实现(Python)
def merge_sort(arr):
if len(arr) <= 1: return arr
mid = len(arr) // 2
left = merge_sort(arr[:mid])
right = merge_sort(arr[mid:])
return merge(left, right)
def merge(left, right):
res = []
i = j = 0
while i < len(left) and j < len(right):
if left[i] <= right[j]: # 注意:≤保证稳定性
res.append(left[i]); i += 1
else:
res.append(right[j]); j += 1
res.extend(left[i:] or right[j:])
return res
3. 性能分析
指标 | 详情 |
---|---|
时间复杂度 | 稳定O(n log n)(任何情况) |
空间复杂度 | O(n)(需额外数组存储合并结果) |
稳定性 | ✅ 稳定(合并时优先取左组元素) |
4. 面试考点
- 稳定性应用:多字段排序(如先按价格排序,再按销量排序,价格相同的保持原顺序)。
- 迭代写法:避免递归栈溢出(用循环模拟分组合并)。
- 链表排序优势:无需随机访问,适合链表数据结构(如Java的
Collections.sort()
)。
⚖️ 三、快速排序 vs 归并排序:面试对比表
维度 | 快速排序 | 归并排序 |
---|---|---|
时间复杂度 | 平均O(n log n),最坏O(n²) | 稳定O(n log n) |
空间复杂度 | 平均O(log n)(递归栈) | O(n)(额外数组) |
稳定性 | ❌ 不稳定 | ✅ 稳定 |
适用场景 | 大规模随机数据,内存敏感 | 需稳定性、链表排序、外部排序 |
优化方向 | 随机基准、小规模转插入排序 | 迭代写法、空间复用(难) |
💡 四、面试高频问题与回答思路
-
快排最坏情况如何优化?
→ 答:最坏发生在数组有序时。优化:随机选基准 + 小规模转插入排序。 -
归并排序为何稳定?快排为何不稳定?
→ 答:归并合并时优先取左组元素;快排的分区交换可能导致相等元素移位(例:[3A, 3B] → [3B, 3A])。 -
时间空间复杂度如何推导?
- 快排:理想递归树高log n,每层分区O(n) → O(n log n);最坏树高n → O(n²)。
- 归并:递归树高log n,每层合并O(n) → O(n log n);合并需临时数组 → O(n)。
重点记忆时间复杂度对比、稳定性差异及优化策略,辅以生活化类比加深印象。加油! 🚀