剑指 Offer 40. 最小的k个数

仅供自己学习

 

思路:
一开始自己用的multiset 做容器,全部加进去再取出k个

代码:

 1 class Solution {
 2 public:
 3     vector<int> getLeastNumbers(vector<int>& arr, int k) {
 4         multiset<int> a;
 5         vector<int> res;
 6         for(int i=0;i<arr.size();++i){
 7             a.insert(arr[i]);
 8         }
 9         multiset<int>::iterator p=a.begin();
10         int count=0;
11         while(count<k){
12             count++;
13             res.push_back(*p++);
14         }
15         return res;
16     }
17 };

 

然后就是直接调用sort函数,再取出前面k个

 

 1 class Solution {
 2 public:
 3     vector<int> getLeastNumbers(vector<int>& arr, int k) {
 4         vector<int> res;
 5         sort(arr.begin(),arr.end());
 6         for(int i=0;i<k;++i){
 7             res.push_back(arr[i]);
 8         }
 9         return res;
10     }
11 };

 

还有就是用大顶堆了。我也是考虑全部加进去再取出k次堆顶元素。

 1 class Solution {
 2 public:
 3     vector<int> getLeastNumbers(vector<int>& arr, int k) {
 4         int n=arr.size();
 5         vector<int> res;
 6         if(k==0) return res;
 7         priority_queue<int,vector<int>,greater<int>> pq;
 8         for(int i=0;i<n;++i){
 9             pq.push(arr[i]);
10         }
11         while(k--){
12             res.push_back(pq.top());pq.pop();
13 
14         }
15         return res;
16     }
17 };

 

堆的话还可以只开k个空间,先把arr的前k个元素加入进堆里,然后每次判断如果栈顶元素大于arr[ i ]的元素就pop再加入arr[ i ]。最后再从堆里取出全部元素即可

代码:

 1 class Solution {
 2 public:
 3     vector<int> getLeastNumbers(vector<int>& arr, int k) {
 4         int n=arr.size();
 5         vector<int> res;
 6         if(k==0) return res;
 7         priority_queue<int,vector<int>,less<int>> pq;
 8         for(int i=0;i<k;++i){
 9             pq.push(arr[i]);
10         }
11         for(int i=k;i<n;++i){
12             if(pq.top()>arr[i]){
13                 pq.pop();
14                 pq.push(arr[i]);
15             }
16         }
17         while(!pq.empty()){
18             res.push_back(pq.top());
19             pq.pop();
20         }
21         return res;
22     }
23 };

 

还有对快排进行优化

这里有一个称为哨兵的标记,用于作为比较的基准点。我们从两侧开始移动,先移动右侧的指针,从最后一个往前移动判断是否小于基准点的值,如果小于那么就停止移动右指针,开始移动左指针,如果遇到的值大于基准点,那么久交换左右指针指向的的元素。交换后再次循环,知道左右指针指向同一个位置。然后将这个位置的元素和基准点交换位置。然后判断基准点的位置是否小于K或者大于K。因为前面这样做了之后,前面的点都是小于基准点的,后面的都是大于基准点的。所以要这样判断来减少不需要的额外循环。但我们确定了他大于K,那么我们就继续快排 数组第一个元素到基准点位置-1的范围的元素。如果小于K,那么就快排 基准点下一个元素到数组最后一个元素的范围。如果基准点等于K,那么就返回结果即可

 

代码:

 1 class Solution {
 2 public:
 3     vector<int> quick_sort(vector<int>&arr,int k,int left,int right){
 4         int l=left,r=right;
 5         vector<int> res;
 6         while(l<r){
 7             while(l<r&&arr[r]>=arr[left]) --r;
 8             while(l<r&&arr[l]<=arr[left]) ++l;
 9             swap(arr[l],arr[r]);
10         }
11         swap(arr[l],arr[left]);
12         if(l>k) return quick_sort(arr,k,left,l-1);
13         if(l<k) return quick_sort(arr,k,l+1,right);
14         res.assign(arr.begin(),arr.begin()+k);
15         return res;
16     }
17     vector<int> getLeastNumbers(vector<int>& arr, int k) {
18         if(k>=arr.size()) return arr;
19         return quick_sort(arr,k,0,arr.size()-1);
20     }
21 };

 

posted @ 2021-03-24 18:43  Mrsdwang  阅读(28)  评论(0)    收藏  举报