剑指 Offer 40. 最小的k个数
剑指 Offer 40. 最小的k个数
输入整数数组 arr ,找出其中最小的 k 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。
思路
方法一:排序
对原数组从小到大排序后取出前 k 个数即可。时间复杂度为O(nlogn)
方法二:堆
用一个大根堆实时维护数组的前 k 小值。时间复杂度为O(nlogk)
方法三:快排思想
注意,题目只需要返回最小的 k 个数字,而没有要求这 k 个数字一定是有序的。
期望复杂度为O(n):n+n/2+n/4+...n/n = 2n-1
最坏情况下的时间复杂度O(n^2)
代码
方法三
partition不用判断l<=r,因为k<=arr.size()
class Solution {
public:
int partition(vector<int> &arr, int l, int r) {
int pivot = arr[l];
int i = l + 1;
for (int j = i; j <= r; j++) {
if (arr[j] < pivot) {
swap(arr[j], arr[i]);
i += 1;
}
}
swap(arr[l], arr[i-1]);
return i-1;
}
int calc(vector<int> &arr, int l, int r, int k) {
int i = partition(arr, l, r);
if (i - l == k) return i - 1;
if (i - l + 1 == k) return i;
if (k > i - l + 1) return calc(arr, i+1, r, k - (i-l+1));
return calc(arr, l, i-1, k);
}
vector<int> getLeastNumbers(vector<int>& arr, int k) {
int i = calc(arr, 0, arr.size()-1, k);
vector<int> ans(arr.begin(), arr.begin()+i+1);
return ans;
}
};
方法二
class Solution {
public:
vector<int> getLeastNumbers(vector<int>& arr, int k) {
vector<int> ans;
if (k == 0) return ans;
priority_queue<int> q;
for (int i = 0; i < k; ++i) {
q.push(arr[i]);
}
for (int i = k; i < arr.size(); ++i) {
if (arr[i] < q.top()) {
q.pop();
q.push(arr[i]);
}
}
while (!q.empty()) {
ans.push_back(q.top());
q.pop();
}
// reverse(ans.begin(), ans.end());
return ans;
}
};
欢迎转载,转载请注明出处!