最小的k个数

题目描述

  输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,
  解法1:基于Partition函数的时间复杂度为O(n)的解法,只有当我们可以修改原始数组时可用
 1 class Solution {
 2 public:
 3     int Partition(vector<int> &input, int begin, int end)
 4     {
 5         int tmp=input[begin];
 6         while(begin<end)
 7         {
 8             while(begin<end && input[end]>=tmp)--end;
 9             input[begin]=input[end];
10             while(begin<end && input[begin]<=tmp)++begin;
11             input[end]=input[begin];
12         }
13         input[begin]=tmp;
14         return begin;
15     }
16     vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
17         int length=input.size();
18         vector<int> res;
19         if(length==0 || k>length || k<=0)return res;
20         int begin=0;
21         int end=length-1;
22         while(true)
23         {
24             int mid=Partition(input, begin, end);
25             if(mid==k)break;
26               if(mid>k)end=mid-1;
27             else begin=mid+1;
28         }
29         for(int idx=0; idx<k; ++idx)
30         {
31             res.push_back(input[idx]);
32         }
33         return res;
34     }
35 };

  解法2:时间复杂度为O(nlogk)的算法。遍历数组,用multiset(底层为红黑树)来存放最小的k个数

 1 class Solution {
 2 public:
 3     vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
 4         int length=input.size();
 5         vector<int> res;
 6         if(length==0 || k<=0 || k>length)return res;
 7         std::multiset<int, std::greater<int>> minSet;
 8         for(int idx=0; idx<length; ++idx)
 9         {
10             if(minSet.size()<k)minSet.insert(input[idx]);
11             else{
12                 std::multiset<int>::iterator it=minSet.begin();
13                 if(*it>input[idx])
14                 {
15                     minSet.erase(it);
16                     minSet.insert(input[idx]);
17                 }
18             }
19         }
20         for(auto it=minSet.begin(); it!=minSet.end(); ++it)
21         {
22             res.push_back(*it);
23         }
24         return res;
25     }
26 };

   解法3:时间复杂度为O(nlogk)的算法。遍历数组,用大顶堆来存放最小的k个数

 1 void heapAdjust(vector<int> &heap)
 2 {
 3     int parent=0;
 4     int child=2*parent+1;
 5     while(child<heap.size())
 6     {
 7         if(child+1<heap.size() && heap[child+1]>heap[child])++child;
 8         if(heap[parent]<heap[child])
 9         {
10             int tmp=heap[parent];
11             heap[parent]=heap[child];
12             heap[child]=tmp;
13         }
14         parent=child;
15         child=2*parent+1;
16     }
17 }
18 vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
19 {
20     if(input.size()<=k)return input;;
21     vector<int> heap;
22     if(k<=0)return heap;
23     for(int i=0; i<k; ++i)heap.push_back(INT_MAX);
24     for(int i=0; i<input.size(); ++i)
25     {
26         if(input[i]<heap[0])
27         {
28             heap[0]=input[i];
29             heapAdjust(heap);//调整大顶堆
30         }
31     }
32     return heap;
33 }

 

posted @ 2017-12-27 10:25  jeysin  阅读(123)  评论(0编辑  收藏  举报