题目
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
分析
本题最简答的思路就是利用快速排序对数组进行排序,然后将遍历数组将最小的K个数输出即可。但是这样时间复杂度将会是 O ( n l o g n ) O(nlogn) O(nlogn),这样不够高效。解决该问题有两种方式,一种是借助快速排序思想将最小的前K个数移动到数组前面即可,时间复杂度将会是 O ( n ) O(n) O(n),但是无法适应大数据集场景。另一种思路就是利用最大堆来处理该问题,并可以适应海量数据集场景,其时间复杂度为 O ( n l o g k ) O(nlogk) O(nlogk)。
借助快速排序思想的思路如下:
- 数组为空或k=0或者k大于数组长度则返回空;
- 划分数组,将小数放到数组前面,大数放到数组后面,并得到划分的下标pivot,若pivot不等于k-1则一直循环上述操作;
利用最大堆的思路如下:
- 数组为空或k=0或者k大于数组长度则返回空;
- 否则初始化最大堆,遍历数组元素,将数组元素依次加入到最大堆,当最大堆大小为k时开始判断,数组元素是否小于堆顶元素,若是则将堆顶元素弹出,将数组元素加入最大堆,那么最后最大堆剩下的k个元素就是数组最小前K个元素。
github链接:JZ29-最小的K个数
C++ 代码
1. 快速排序思想
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
int size = input.size();
if(size == 0 || k == 0 || k > size){
vector<int> ans;
return ans;
}
int low = 0,high = size-1;
int pivot = Partition(input,low,high);
while(pivot != k-1){
if(pivot > k-1){
high = pivot-1;
pivot = Partition(input,low,high);
}else{
low = pivot + 1;
pivot = Partition(input,low,high);
}
}
vector<int> ans(k);
for(int i = 0 ; i < k ; i++){
ans[i] = input[i];
}
return ans;
}
int Partition(vector<int> &input,int low,int high){
int pivot = input[low];
while(low < high){
while(low < high && input[high] >= pivot){
high--;
}
input[low] = input[high];
while(low < high && input[low] <= pivot){
low++;
}
input[high] = input[low];
}
input[low] = pivot;
return low;
}
};
int main()
{
int n,k;
while(cin>>n>>k){
vector<int> array(n);
for(int i = 0 ; i < n ; i++){
cin>>array[i];
}
Solution s;
vector<int> ans = s.GetLeastNumbers_Solution(array,k);
for(int i = 0 ; i < k ; i++){
cout<<ans[i]<<" ";
}
}
return 0;
}
2.最大堆思想
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct cmp{
bool operator ()(const int &a,const int &b){
return a < b;
}
};
class Solution {
public:
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
int size = input.size();
if(size == 0 || k == 0 || k > size){
vector<int> ans;
return ans;
}
vector<int> ans(k);
priority_queue<int,vector<int> ,cmp> q;
for(int i = 0 ; i < size ; i++){
if(q.size() < k){
q.push(input[i]);
}else{
if(input[i] < q.top()){
//cout<<q.top()<<endl;
q.pop();
q.push(input[i]);
}else{
continue;
}
}
}
for(int i = 0 ; i < k ; i++){
ans[i] = q.top();
q.pop();
}
return ans;
}
};
int main()
{
int n,k;
while(cin>>n>>k){
vector<int> array(n);
for(int i = 0 ; i < n ; i++){
cin>>array[i];
}
Solution s;
vector<int> ans = s.GetLeastNumbers_Solution(array,k);
for(int i = 0 ; i < k ; i++){
cout<<ans[i]<<" ";
}
}
return 0;
}