最小的k个数
最小的K个数
https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=295&tqId=23263&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj
最小的k个数
方法一:用vector中的sort函数进行排序
思路:
vector<int>input;
sort(input.begin(),input.end())
return vector<int>({input.begin(),input.begin()+k});
代码:
class Solution{
public:
vector<int> GetLeastNumbers_Solution(vector<int> input,int k){
vector<int> res;
if(k==0||k>input.size()){
return res;
}
//vector中自带的sort函数进行排序
sort(input.begin(),input.end());
//返回排序后的前k小的数
return vector<int>({input.begin(),input.begin()+k});
}
};
方法二:用k大小的堆构造一个优先队列
思路:
1.只要优先队列中的元素的个数还是小于k,则 直接将数插入队列中
2.否则就与队首的元素进行比较,如果比队首的元素小,则让队首元素出队列
代码:
class Solution{
public:
//定义一个容器用来存排序后的元素的数组,传入需要排序的数组,以及输出第k个小的数
vector<int> GetLeastNumbers_Solution(vector<int> input,int k){
//定义一个数组用来存排序的k个数
vector<int>res;
//如果需要输出的是第0小的数,或需要输出的k个数比总的元素少,则直接返回
if(k==0||k>input.size()){
return res;
}
//定义一个优先队列
priority_queue<int,vector<int>> q;
//遍历整个序列,如果发现优先队列中的元素个数少于k,那么就直接将元素放入队列中
//否则就与队首的元素进行比较,如果发现队首的元素大于想要的插入的数,就让队首出队,
//让新的这个元素插入队尾
for(const int val:input){
if(q.size()<k){
q.push(val);
}else{
if(q.top()>val){
q.pop();
q.push(val);
}
}
}
//将优先队列中的所有元素插入容器res中
while(!q.empty()){
res.push_back(q.top());
q.pop();
}
return res;
}
};
方法三:快排+二分
思路:
对数组[l, r]一次快排partition过程可得到,[l, p), p, [p+1, r)三个区间,[l,p)为小于等于p的值[p+1,r)为大于等于p的值。
然后再判断p,利用二分法
如果[l,p), p,也就是p+1个元素(因为下标从0开始),如果p+1 == k, 找到答案
如果p+1 < k, 说明答案在[p+1, r)区间内,
如果p+1 > k , 说明答案在[l, p)内
代码:
class Solution{
public:
int partition(vector<int> &t,int l,int r){
//设置一个基准数:这里设置最后一个数为基准数
//设置两个同方向的指针:i=0(找比基准大的数),j=0(找比基准小的数)
int temp=t[r-1];
int i=l;
//让j指针遍历除了最后一个数之外的所有的数
//如果发现一个小于基准的数,就将其与i对应的数交换,i与j指针都向后移动一位
//否则就将j移动,直到找到一个比基准小的数,再进行就交换
for(int j=l;j<r-1;j++){
if(t[j]<temp){
swap(t[i++],t[j]);
}
}
//最后将最后一个数(不一定是原先的temp),与i指向的数交换
swap(t[r-1],t[i]);
return i;
}
vector<int> GetLeastNumbers_Solution(vector<int> input,int k){
vector<int>res;
if(k==0||input.size()<k){
return res;
}
//快排设置两个指针:左指针l=0,右指针r=input.size()
int l=0,r=input.size();
//快排:只要所有指针还没有相交,就继续
while(l<r){
int p=partition(input,l,r);
//由于下标从0开始,所以元素个数时p+1
//如果够了k个,就直接返回左区间
if(p+1==k){
return vector<int>({input.begin(),input.begin()+k});
}
//如果还不够k个元素,就继续再右区间中去找,所以更新l=p+1
if(p+1<k){
l=p+1;
}else {
//如果超过了,就让 右指针指向p,因为答案在[l,p)之间
//由于传入p的时候会取p-1的数为基准,所以是在[l,p)中找
r=p;
}
}
return res;
}
};