文章目录
- 排序算法对比
- 基本概要
- 算法逐一介绍
- 1. 冒泡排序(Bubble Sort)
- 2. 选择排序(Selection Sort)
- 3. 插入排序(Insertion Sort)🌟🌟
- 4. 希尔排序(Shell Sort)
- 5. 归并排序(Merge Sort)🌟🌟
- 6. 快速排序(Quick Sort)🌟🌟🌟🌟🌟🌟
- 7. 堆排序(Heap Sort)🌟🌟
- 8. 计数排序(Counting Sort)
- 9. 桶排序(Bucket Sort)
- 10. 基数排序(Radix Sort)
- 总结
- 关于备考
- ✅ 必考 or 高频排序算法
- 🎯 企业面试中高频考察点
- 🧠 拓展建议
- 🎯 排序算法面试核心知识清单
- ✅ 高频要求手写的排序算法
- 🔝 面试高频 Leetcode 题目(附关键词)
- 🧩 排序面试思维框架(你可以这样答)
- 🌟 经典问题:快速排序的时间复杂度?
- 🌟 高级问题:为什么说归并适合链表?
- 🌟 扩展:非比较类排序的适用场景?
- 🧠 排序算法复习笔记(面试 & 考试专用)
- 一、排序算法分类
- 二、常考排序算法精讲
- 1. 快速排序(Quick Sort)
- 2. 归并排序(Merge Sort)
- 3. 堆排序(Heap Sort)
- 4. 插入排序(Insertion Sort)
- 5. 计数排序(Counting Sort)
- 6. 基数排序(Radix Sort)
- 三、面试高频题推荐
- 四、应答框架 & 面试建议
- 五、实战建议
本文将介绍常见排序算法,包括算法思想、代码实现(C++和Python)、时间复杂度对比及不同排序间的比较。
排序算法对比
基本概要
排序算法大体可分为两种:
- 比较排序,时间复杂度O(nlogn) ~ O(n^2),主要有:冒泡排序,选择排序,插入排序,归并排序,堆排序,快速排序等。
- 非比较排序,时间复杂度可以达到O(n),主要有:计数排序,基数排序,桶排序等。
- 关于排序算法的稳定性问题:排序算法稳定性的简单形式化定义为:如果
arr[i] = arr[j]
,排序前arr[i]
在arr[j]
之前,排序后arr[i]
还在arr[j]
之前,则称这种排序算法是稳定的。通俗地讲就是保证排序前后两个相等的数的相对顺序不变。(可以通过自定义比较函数来去除稳定性问题)
举例:对于冒泡排序,原本是稳定的排序算法,如果将记录交换的条件改成arr[i] >= arr[i + 1],则两个相等的记录就会交换位置,从而变成不稳定的排序算法。
排序算法 | 平均时间复杂度 | 最好情况 | 最坏情况 | 空间复杂度 | 稳定性 | 适用场景 | 是否原地 |
---|---|---|---|---|---|---|---|
冒泡排序 | O(n²) | O(n) | O(n²) | O(1) | 稳定 | 小数据或基本有序 | 是 |
选择排序 | O(n²) | O(n²) | O(n²) | O(1) | 不稳定 | 小数据,交换次数少,通用 | 是 |
插入排序 | O(n²) | O(n) | O(n²) | O(1) | 稳定 | 小数据或基本有序 | 是 |
希尔排序 | O(n log n) ~ O(n²) | O(n logn) | O(n²) | O(1) | 不稳定 | 中等数据量,通用 | 是 |
归并排序 | O(n log n) | O(n log n) | O(n log n) | O(n) | 稳定 | 链表/大数据量,稳定排序 | 否 |
快速排序 | O(n log n) | O(n log n) | O(n²) | O(log n) | 不稳定 | 通用排序,平均最快 | 是 |
堆排序 | O(n log n) | O(n log n) | O(n log n) | O(1) | 不稳定 | 通用排序,避免最坏情况 | 是 |
计数排序 | O(n +k) | O(n +k) | O(n +k) | O(k) | 稳定 | 整数,范围小 | 否 |
桶排序 | O(n +k) | O(n +k) | O(n²) | O(n +k) | 稳定 | 均匀分布数据,浮点数 | 否 |
基数排序 | O(d(n +k)) | O(d(n +k)) | O(d(n +k)) | O(n +k) | 稳定 | 多位数整数 | 否 |
算法逐一介绍
1. 冒泡排序(Bubble Sort)
- 思想:相邻元素比较交换,将最大元素逐步“冒泡”到末尾。
- 时间复杂度:
- 平均/最坏:O(n²)
- 最好(已有序):O(n)
- 空间复杂度:O(1)
- 稳定性:稳定
C++代码:
void bubbleSort(int arr[], int n) {for (int i = 0; i < n-1; i++) {bool swapped = false;for (int j = 0; j < n-i-1; j++) {if (arr[j] > arr[j+1]) {swap(arr[j], arr[j+1]);swapped = true;}}if (!swapped) break;}
}
//---------------------------
void bubbleSort(vector<int>& arr) {int n = arr.size();for(int i = 0; i < n - 1; ++i)for(int j = 0; j < n - i - 1; ++j)if(arr[j] > arr[j + 1])swap(arr[j], arr[j + 1]);
}
Python代码:
def bubble_sort(arr):n = len(arr)for i in range(n-1):swapped = Falsefor j in range(n-i-1):if arr[j] > arr[j+1]:arr[j], arr[j+1] = arr[j+1], arr[j]swapped = Trueif not swapped:breakreturn arr
----------------------------------------
def bubble_sort(arr):n = len(arr)for i in range(n - 1):for j in range(n - i - 1):if arr[j] > arr[j + 1]:arr[j], arr[j + 1] = arr[j + 1], arr[j]
2. 选择排序(Selection Sort)
- 思想:每次选择最小元素放到已排序序列末尾。
- 时间复杂度:
- 平均/最好/最坏:O(n²)
- 空间复杂度:O(1)
- 稳定性:不稳定
C++代码:
void selectionSort(vector<int>& arr) {int n = arr.size();for(int i = 0; i < n - 1; ++i) {int min_idx = i;for(int j = i + 1; j < n; ++j)if(arr[j] < arr[min_idx])min_idx = j;swap(arr[i], arr[min_idx]);}
}
Python代码:
def selection_sort(arr):n = len(arr)for i in range(n-1):min_idx = ifor j in range(i+1, n):if arr[j] < arr[min_idx]:min_idx = jarr[i], arr[min_idx] = arr[min_idx], arr[i]return arr
3. 插入排序(Insertion Sort)🌟🌟
- 思想:逐个将元素插入到已排序序列的正确位置。当前元素向左找合适位置插入。
- 时间复杂度:
- 平均/最坏:O(n²)
- 最好(已有序):O(n)
- 空间复杂度:O(1)
- 稳定性:稳定
C++代码:
void insertionSort(vector<int>& arr) {//int n = arr.size();for(int i = 1; i < n; ++i) {int key = arr[i];int j = i - 1;while(j >= 0 && arr[j] > key)arr[j + 1] = arr[j--];arr[j + 1] = key;}
}
Python代码:
def insertion_sort(arr):for i in range(1, len(arr)):key = arr[i]j = i - 1while j >= 0 and arr[j] > key:arr[j + 1] = arr[j]j -= 1arr[j + 1] = keyreturn arr
4. 希尔排序(Shell Sort)
- 思想:分组插入排序,逐步缩小间隔。插入排序的优化,分组进行插入。
- 时间复杂度:O(nlogn) ~ O(n²)(取决于间隔序列)
- 空间复杂度:O(1)
- 稳定性:不稳定
C++代码:
void shellSort(int arr[], int n) {for (int gap = n/2; gap > 0; gap /= 2) {for (int i = gap; i < n; i++) {int temp = arr[i], j;for (j = i; j >= gap && arr[j-gap] > temp; j -= gap)arr[j] = arr[j-gap];arr[j] = temp;}}
}
----------------------------------------------------
void shellSort(vector<int>& arr) {int n = arr.size();for(int gap = n/2; gap > 0; gap /= 2) {for(int i = gap; i < n; ++i) {int temp = arr[i], j = i;while(j >= gap && arr[j - gap] > temp) {arr[j] = arr[j - gap];j -= gap;}arr[j] = temp;}}
}
Python代码:
def shell_sort(arr):n = len(arr)gap = n // 2while gap > 0:for i in range(gap, n):temp = arr[i]j = iwhile j >= gap and arr[j-gap] > temp:arr[j] = arr[j-gap]j -= gaparr[j] = tempgap //= 2return arr
5. 归并排序(Merge Sort)🌟🌟
- 思想:分治法,递归排序后合并。分而治之,分成小块合并排序。
- 时间复杂度:O(n log n)
- 空间复杂度:O(n)
- 稳定性:稳定
- 图示:
图源
C++代码:
void merge(int arr[], int l, int m, int r) {int n1 = m - l + 1, n2 = r - m;int L[n1], R[n2];for (int i = 0; i < n1; i++) L[i] = arr[l+i];for (int j = 0; j < n2; j++) R[j] = arr[m+1+j];int i = 0, j = 0, k = l;while (i < n1 && j < n2) {if (L[i] <= R[j]) arr[k++] = L[i++];else arr[k++] = R[j++];}while (i < n1) arr[k++] = L[i++];while (j < n2) arr[k++] = R[j++];
}void mergeSort(int arr[], int l, int r) {if (l >= r) return;int m = l + (r - l)/2;mergeSort(arr, l, m);mergeSort(arr, m+1, r);merge(arr, l, m, r);
}
-----------------------
void merge(vector<int>& arr, int l, int m, int r) {vector<int> left(arr.begin() + l, arr.begin() + m + 1);vector<int> right(arr.begin() + m + 1, arr.begin() + r + 1);int i = 0, j = 0, k = l;while(i < left.size() && j < right.size())arr[k++] = left[i] < right[j] ? left[i++] : right[j++];while(i < left.size()) arr[k++] = left[i++];while(j < right.size()) arr[k++] = right[j++];
}void mergeSort(vector<int>& arr, int l, int r) {if(l >= r) return;int m = l + (r - l) / 2;mergeSort(arr, l, m);mergeSort(arr, m + 1, r);merge(arr, l, m, r);
}
Python代码:
def merge_sort(arr):if len(arr) > 1:mid = len(arr) // 2L, R = arr[:mid], arr[mid:]merge_sort(L)merge_sort(R)i = j = k = 0while i < len(L) and j < len(R):if L[i] < R[j]:arr[k] = L[i]i +=1else:arr[k] = R[j]j +=1k +=1while i < len(L):arr[k] = L[i]i +=1; k +=1while j < len(R):arr[k] = R[j]j +=1; k +=1return arr
-----------------------------------------------------
def merge_sort(arr):if len(arr) <= 1:return arrmid = len(arr)//2left = merge_sort(arr[:mid])right = merge_sort(arr[mid:])return merge(left, right)def merge(left, right):result = []i = j = 0while i < len(left) and j < len(right):if left[i] < right[j]:result.append(left[i])i += 1else:result.append(right[j])j += 1result.extend(left[i:])result.extend(right[j:])return result
6. 快速排序(Quick Sort)🌟🌟🌟🌟🌟🌟
- 思想:分治法,选基准分区,递归排序。选一个基准值,小的放左边,大的放右边。通过一趟排序将待排数据分割成独立的两部分,其中一部分的所有数据都比另一部分小,再递归地对这两部分进行排序。采用“分治”的思想,对于一组数据,选择一个基准元素(base),通常选择第一个或最后一个元素,通过第一轮扫描,比base小的元素都在base左边,比base大的元素都在base右边,再有同样的方法递归排序这两部分,直到序列中所有数据均有序为止。
- 时间复杂度:
- 平均/最好:O(nlogn)
- 最坏(已有序):O(n²)
- 空间复杂度:O(log n)(递归栈)
- 稳定性:不稳定
- 核心步骤
-
选择基准值(Pivot)
从数组中选择一个元素作为基准值(pivot),通常选择最后一个元素、第一个元素或随机元素。 -
分区(Partition)
将数组重新排列,使得所有小于基准值的元素放在基准值的左侧,所有大于基准值的元素放在右侧。
分区结束后,基准值的位置即为最终排序后的正确位置。 -
递归排序
对基准值左侧和右侧的子数组递归地进行快速排序。
-
C++代码:
int partition(vector<int>& arr, int low, int high) {int pivot = arr[high], i = low - 1;for(int j = low; j < high; ++j) {if(arr[j] <= pivot){i++;swap(arr[i], arr[j]);//swap(arr[++i], arr[j]);}}swap(arr[i + 1], arr[high]);return i + 1;
}void quickSort(vector<int>& arr, int low, int high) {if(low < high) {int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}
}
Python代码:
def quick_sort(arr):if len(arr) <= 1:return arrpivot = arr[-1]left = [x for x in arr[:-1] if x <= pivot]right = [x for x in arr[:-1] if x > pivot]return quick_sort(left) + [pivot] + quick_sort(right)
7. 堆排序(Heap Sort)🌟🌟
- 思想:构建最大堆,交换堆顶元素并调整堆。利用堆(最大堆)结构,每次取出堆顶元素放到数组尾部。
- 时间复杂度:O(n log n)
- 空间复杂度:O(1)
- 稳定性:不稳定
C++代码:
void heapify(vector<int>& arr, int n, int i) {int largest = i, left = 2 * i + 1, right = 2 * i + 2;if(left < n && arr[left] > arr[largest]) largest = left;if(right < n && arr[right] > arr[largest]) largest = right;if(largest != i) {swap(arr[i], arr[largest]);heapify(arr, n, largest);}
}void heapSort(vector<int>& arr) {int n = arr.size();for(int i = n / 2 - 1; i >= 0; --i)heapify(arr, n, i);for(int i = n - 1; i > 0; --i) {swap(arr[0], arr[i]);heapify(arr, i, 0);}
}
Python代码:
def heapify(arr, n, i):largest = il, r = 2 * i + 1, 2 * i + 2if l < n and arr[l] > arr[largest]:largest = lif r < n and arr[r] > arr[largest]:largest = rif largest != i:arr[i], arr[largest] = arr[largest], arr[i]heapify(arr, n, largest)def heap_sort(arr):n = len(arr)for i in range(n // 2 - 1, -1, -1):heapify(arr, n, i)for i in range(n - 1, 0, -1):arr[0], arr[i] = arr[i], arr[0]heapify(arr, i, 0)return arr
8. 计数排序(Counting Sort)
- 思想:统计元素出现次数,按顺序输出。
- 时间复杂度:O(n + k)(k为数据范围)
- 空间复杂度:O(k)
- 稳定性:稳定
C++代码:
void countingSort(int arr[], int n, int max_val) {int output[n], count[max_val+1] = {0};for (int i = 0; i < n; i++) count[arr[i]]++;for (int i = 1; i <= max_val; i++) count[i] += count[i-1];for (int i = n-1; i >=0; i--) output[--count[arr[i]]] = arr[i];for (int i = 0; i < n; i++) arr[i] = output[i];
}
-------------------------------------------
void countingSort(vector<int>& arr) {if(arr.empty()) return;int max_val = *max_element(arr.begin(), arr.end());vector<int> count(max_val + 1, 0);for(int num : arr) ++count[num];int index = 0;for(int i = 0; i <= max_val; ++i)while(count[i]--) arr[index++] = i;
}
Python代码:
def counting_sort(arr):max_val = max(arr)count = [0] * (max_val + 1)for num in arr:count[num] +=1i = 0for num in range(max_val +1):while count[num] >0:arr[i] = numi +=1count[num] -=1return arr
--------------------------------------------------
def counting_sort(arr):if not arr:returnmax_val = max(arr)count = [0] * (max_val + 1)for num in arr:count[num] += 1idx = 0for i, c in enumerate(count):for _ in range(c):arr[idx] = iidx += 1
9. 桶排序(Bucket Sort)
- 思想:分桶后分别排序,合并结果。把数据分布到若干桶中,桶内排序,再合并结果。
- 时间复杂度:
- 平均:O(n + k)
- 最坏:O(n²)
- 空间复杂度:O(n + k)
- 稳定性:稳定(取决于桶内排序算法)
C++代码:
void bucketSort(float arr[], int n) {vector<float> buckets[n];for (int i = 0; i < n; i++) {int bi = n * arr[i];buckets[bi].push_back(arr[i]);}for (int i = 0; i < n; i++)sort(buckets[i].begin(), buckets[i].end());int index = 0;for (int i = 0; i < n; i++)for (float num : buckets[i])arr[index++] = num;
}
-----------------------------------------------
void bucketSort(vector<float>& arr) {int n = arr.size();vector<vector<float>> buckets(n);for(float num : arr) {int index = num * n;buckets[index].push_back(num);}for(auto& bucket : buckets)sort(bucket.begin(), bucket.end());arr.clear();for(auto& bucket : buckets)arr.insert(arr.end(), bucket.begin(), bucket.end());
}
Python代码:
def bucket_sort(arr):max_val, min_val = max(arr), min(arr)bucket_size = (max_val - min_val) / len(arr)buckets = [[] for _ in range(len(arr))]for num in arr:idx = int((num - min_val) // bucket_size)if idx == len(buckets):idx -=1buckets[idx].append(num)sorted_arr = []for bucket in buckets:sorted_arr.extend(sorted(bucket))return sorted_arr
-------------------------------------------------
def bucket_sort(arr):if len(arr) == 0:returnn = len(arr)buckets = [[] for _ in range(n)]for num in arr:index = int(num * n)buckets[index].append(num)for bucket in buckets:bucket.sort()idx = 0for bucket in buckets:for num in bucket:arr[idx] = numidx += 1
10. 基数排序(Radix Sort)
- 思想:按位排序,从低位到高位。从低位到高位对数字排序,使用稳定排序如计数排序。
- 时间复杂度:O(d(n + k))(d为位数)
- 空间复杂度:O(n + k)
- 稳定性:稳定
C++代码:
void countingSortForRadix(int arr[], int n, int exp) {int output[n], count[10] = {0};for (int i = 0; i < n; i++) count[(arr[i]/exp)%10]++;for (int i = 1; i < 10; i++) count[i] += count[i-1];for (int i = n-1; i >=0; i--) {output[count[(arr[i]/exp)%10]-1] = arr[i];count[(arr[i]/exp)%10]--;}for (int i = 0; i < n; i++) arr[i] = output[i];
}void radixSort(int arr[], int n) {int max_val = *max_element(arr, arr+n);for (int exp = 1; max_val/exp >0; exp *=10)countingSortForRadix(arr, n, exp);
}
--------------------------------
void countingSortByDigit(vector<int>& arr, int exp) {int n = arr.size();vector<int> output(n), count(10, 0);for(int i = 0; i < n; ++i)count[(arr[i] / exp) % 10]++;for(int i = 1; i < 10; ++i)count[i] += count[i - 1];for(int i = n - 1; i >= 0; --i) {output[count[(arr[i] / exp) % 10] - 1] = arr[i];count[(arr[i] / exp) % 10]--;}arr = output;
}void radixSort(vector<int>& arr) {int max_val = *max_element(arr.begin(), arr.end());for(int exp = 1; max_val / exp > 0; exp *= 10)countingSortByDigit(arr, exp);
}
Python代码:
def radix_sort(arr):max_val = max(arr)exp = 1while max_val // exp >0:counting_sort_by_digit(arr, exp)exp *=10return arrdef counting_sort_by_digit(arr, exp):n = len(arr)output = [0]*ncount = [0]*10for i in range(n):index = (arr[i] // exp) %10count[index] +=1for i in range(1,10):count[i] += count[i-1]for i in range(n-1, -1, -1):index = (arr[i] // exp) %10output[count[index]-1] = arr[i]count[index] -=1for i in range(n):arr[i] = output[i]
---------------------------------------------------
def counting_sort_by_digit(arr, exp):n = len(arr)output = [0] * ncount = [0] * 10for num in arr:index = (num // exp) % 10count[index] += 1for i in range(1, 10):count[i] += count[i - 1]for num in reversed(arr):index = (num // exp) % 10output[count[index] - 1] = numcount[index] -= 1for i in range(n):arr[i] = output[i]def radix_sort(arr):max_val = max(arr)exp = 1while max_val // exp > 0:counting_sort_by_digit(arr, exp)exp *= 10
总结
- 冒泡、选择、插入排序:适用于小规模数据。
- 希尔排序:中等规模数据,优于插入排序。
- 归并、快速、堆排序:大规模数据,归并稳定但需额外空间,快速排序平均最快,堆排序原地排序。
- 计数、桶、基数排序:特定场景下高效(如整数范围小、均匀分布、多位数)。
非常好的问题!在数据结构与算法考试、面试(尤其是大厂)中,虽然排序算法很多,但常考的排序算法主要集中在下面这几种,因为它们代表了不同的思想和场景优化策略:
关于备考
✅ 必考 or 高频排序算法
排序算法 | 说明 / 考察点 | 为什么常考 |
---|---|---|
快速排序 | 分治、原地、非稳定排序 | 最常用的高效通用排序,面试常要求手写 |
归并排序 | 分治、稳定排序、空间换时间 | 经常考在链表中排序(Leetcode经典) |
堆排序 | 二叉堆结构、原地排序、优先队列基础 | 常作为Top K 问题基础 |
插入排序 | 稳定、简单,考察基本理解 | 代码简单,适合考察写基础排序 |
计数排序 | 线性时间排序代表 | 理解适用范围 + 稳定排序基础 |
冒泡排序 | 教学用、面试中考“你写一个最基础排序” | 了解基本交换机制 |
桶/基数排序 | 高效但场景特定 | 高级笔试题中出现,用于浮点/大数据位排序 |
🎯 企业面试中高频考察点
- 写一个快速排序(原地/非递归)
- 链表使用归并排序排序 O(n log n)
- 从数据流中找第K大(堆排序)
- Top K 频率元素(堆 + 计数)
- 计数排序 vs 比较类排序差别(适用场景)
- 给定整数数组用基数排序排序
🧠 拓展建议
方向 | 建议练习题 |
---|---|
📚 基础写法 | 快速排序、归并排序、堆排序手写 |
🔍 排序思想 | 比较类 vs 非比较类排序的适用场景 |
📈 排序优化 | 小数组用插入排序,大数组快速+归并 |
🧪 Leetcode | #215 , #912 , #148 , #347 , #451 等 |
🎯 排序算法面试核心知识清单
✅ 高频要求手写的排序算法
算法 | 重点考察方向 | 稳定性 | 原地 |
---|---|---|---|
快速排序 | 分治思想、原地实现、递归/非递归 | ❌ | ✅ |
归并排序 | 分治思想、链表排序实现 | ✅ | ❌ |
堆排序 | 大顶堆构建、Top K 使用 | ❌ | ✅ |
插入排序 | 简单直接、部分有序数组快 | ✅ | ✅ |
🔝 面试高频 Leetcode 题目(附关键词)
题目编号 | 名称 | 涉及排序类型 | 难度 |
---|---|---|---|
#912 | 排序数组 | 快速/归并排序 | 🟠 中等 |
#215 | 数组第K大元素 | 快排/堆排序 | 🟠 中等 |
#347 | 前K高频元素 | 堆 + 计数排序思想 | 🟠 中等 |
#148 | 链表排序 | 归并排序 | 🔵 困难 |
#451 | 按频率排序 | 计数 + 自定义排序 | 🟠 中等 |
🧩 排序面试思维框架(你可以这样答)
🌟 经典问题:快速排序的时间复杂度?
- 平均:O(n log n)
- 最坏:O(n²)(已排序数组)
- 优化:三路快排、随机pivot
🌟 高级问题:为什么说归并适合链表?
- 不依赖随机访问
- 可以轻松实现O(1)空间的链表归并
- 稳定、时间复杂度始终 O(n log n)
🌟 扩展:非比较类排序的适用场景?
- 计数排序:整数,范围小
- 基数排序:整数、位数小(如手机号、身份证)
- 桶排序:小数、浮点数、分布均匀
🧠 排序算法复习笔记(面试 & 考试专用)
一、排序算法分类
分类 | 算法 | 稳定性 | 是否原地 | 时间复杂度(平均) | 时间复杂度(最坏) | 适用场景 |
---|---|---|---|---|---|---|
比较类排序 | 冒泡、插入、选择、归并、快速、堆 | 插入/冒泡/归并 ✅ 其余 ❌ | 归并 ❌ 其余 ✅ | O(n^2)/O(nlogn) | O(n^2)/O(nlogn) | 通用排序 |
非比较类排序 | 计数、桶、基数 | ✅ | ❌ | O(n)/O(nk) | O(n)/O(nk) | 整数/位数小/范围有限的排序场景 |
二、常考排序算法精讲
1. 快速排序(Quick Sort)
- 思想:分治 + 原地交换
- 特点:高效,最常用,平均 O(nlogn),最坏 O(n^2)
- 代码:C++/Python
- 常考形式:手写实现;找第K大元素;排序 + 去重
2. 归并排序(Merge Sort)
- 思想:分治 + 合并
- 特点:稳定,适合链表,空间复杂度 O(n)
- 常考形式:链表排序;大数据排序
3. 堆排序(Heap Sort)
- 思想:最大堆构建 + 弹出堆顶
- 特点:原地,不稳定,优先队列基础
- 常考形式:Top K 问题,最大/最小K个数
4. 插入排序(Insertion Sort)
- 思想:构建有序序列,将新元素插入
- 特点:适合小数组、基本有序场景
5. 计数排序(Counting Sort)
- 思想:统计频次 -> 回写数组
- 特点:非比较排序,稳定,O(n+k),适合范围小的整数
6. 基数排序(Radix Sort)
- 思想:按位排序(低位到高位)
- 特点:适合大整数排序;与计数结合使用
三、面试高频题推荐
Leetcode 编号 | 题目 | 重点算法 |
---|---|---|
912 | Sort an Array | 快排 / 归并 |
215 | Kth Largest Element in Array | 快排 / 堆排序 |
347 | Top K Frequent Elements | 堆 + 计数排序思想 |
148 | Sort List | 归并(链表版) |
451 | Sort Characters by Frequency | 计数 + 自定义排序 |
四、应答框架 & 面试建议
1. 你知道哪些排序?哪种最好?
- 分析场景再选:快排适合通用,归并适合链表,计数适合整数范围小
2. 快排最坏时间复杂度?怎么优化?
- O(n^2),优化方法:随机化 pivot,三路快排
3. 为什么归并适合链表?
- 链表不能随机访问,归并分治直接分中间节点,合并无需额外数组
4. 如何实现 Top K 问题?
- 小顶堆维护前 K 个元素,堆排序或快速选择法
五、实战建议
- 手写练习:快排(原地)、归并(链表)、堆构建
- 使用库时:记得
sort()
默认用 IntroSort(快排+堆+插入) - 注意稳定性、是否原地、空间复杂度等细节
📌 建议每日刷 1-2 道经典题,注重思维过程而非背代码
📌 可搭配可视化工具(如 Visualgo.net)加深理解