1. 问题背景
在算法面试中,如何高效地从一个无序数组中找出最小的k个数,是一个经典且常见的编程挑战。本文将深入探讨解决这一问题的多种方法,并对各解法的优缺点进行详细分析。
2. 问题描述
给定一个未排序的整数数组 arr
和整数 k
,要求返回数组中最小的 k
个数。需要注意以下边界条件:
- 当
k = 0
时,返回空数组 - 当
k ≥ arr.length
时,返回整个数组
3. 解决方案分析
3.1 暴力交换法(冒泡思想)
算法思路
- 使用双重循环遍历数组
- 通过交换,将最小的k个数依次移动到数组前k个位置
- 时间复杂度:O(n * k)
- 空间复杂度:O(k)
代码实现
vector<int> getLeastNumbers(vector<int>& arr, int k) {
vector<int> result;
int t = 0;
for (int i = 0; i < k; i++) {
for (int j = i+1; j < arr.size(); j++) {
if (arr[i] > arr[j]) {
t = arr[i];
arr[i] = arr[j];
arr[j] = t;
}
}
result.push_back(arr[i]);
}
return result;
}
3.2 排序取前k个(偷懒法)
算法思路
- 直接对整个数组进行排序
- 取排序后数组的前k个元素
- 时间复杂度:O(n log n)
- 空间复杂度:O(log n)(排序的额外空间)
代码实现
vector<int> getLeastNumbers(vector<int>& arr, int k) {
sort(arr.begin