题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
解题思路:
思路1:首先是一个简单的解题思路,利用一个priority_queue的优先队列结构,这个结构的特点是队列首元素是该队列中最大的元素,因此首先将input中的前k个元素压入priority_queue,之后遍历一遍该数组,数组的每一个元素与priority_queue中的首元素进行比较,如果比首元素小则压入priority_queue,弹出首元素即可,时间复杂度主要是priority_queue内部排序造成的O(nlog(k))。
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> ret;
priority_queue<int> ans;
int len = input.size();
if (len < k || k == 0){
return ret;
}
for (int i = 0; i < k; i++){
ans.push(input[i]);
}
for (int i = k; i < len; i++){
if (input[i] < ans.top()){
ans.pop();
ans.push(input[i]);
}
}
//vector<int> ret;
int cnt = k;
while(cnt--){
ret.push_back(ans.top());
ans.pop();
}
return ret;
}
};
思路2:太巧妙了!利用近似O(n)就可以解决问题的算法!利用partition算法的思想(详情请见我的博客Partition 算法详解 + 应用 + 代码实现(一)),每一次遍历数组的时候,都可以先随机确定一个priovot的值,然后不停遍历数组,大于等于privot的都在privot右边,小于等于privot的都在privot左边,当privot左边的长度恰好为k时,遍历结束,输出这k个元素即为答案。
代码如下:
class Solution {
public:
int partition(vector<int> &arr, int beginn, int endd){
int privot = arr[beginn];
while (beginn < endd){
while (beginn < endd && arr[--endd] >= privot);
arr[beginn] = arr[endd];
while (beginn < endd && arr[++beginn] <= privot);
arr[endd] = arr[beginn];
}
arr[endd] = privot;
return beginn;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
vector<int> ret;
int len = input.size();
if (len < k || k == 0){
return ret;
}
int pos = partition(input, 0, len);
while (pos + 1 != k){
if (pos + 1 > k){
pos = partition(input, 0, pos);
}
else if (pos + 1 < k){
pos = partition(input, pos + 1, len);
}
}
for (int i = 0; i < pos + 1; i++){
ret.push_back(input[i]);
}
return ret;
}
};
小白感叹算法真奇妙
本文介绍两种寻找数组中最小K个数的有效方法。一种使用优先队列实现,时间复杂度为O(nlog(k));另一种采用Partition算法思想,平均时间复杂度接近O(n),更高效且巧妙。
1240

被折叠的 条评论
为什么被折叠?



