最小的k个数

题:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

方法一:O(n)的算法,不过要改变数组。

思路:利用快排的思想,以最后一个元素为基准,将数组一分为二,左边小于基准,右边大于基准,完成一次趟分割,基准的下标为index,这时,包括基准在内,左边有index+1个最小元素,若index+1=k,显然复合题意,直接将这index+1个元素输出即可,若不等于:

(1)index>k-1,则前k个最小元素的右端点应该在基准的左边,所以更新查找范围的右端点,重新在左侧找;

(2)index<k-1,则前k个最小元素应该包括基准,且其右端点在基准的右边,所以更新查找范围的左端点,重新在左侧找。

代码如下:

 1 class Solution {
 2 public:
 3     vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
 4          vector<int> res;
 5         if(input.empty()||k>input.size()||k<=0) 
 6             return res;
 7         int len=input.size();
 8         int start=0;
 9         int end=len-1;
10         int index=partition(input,start,end);
11         while(index !=k-1)
12         {
13             if(index>k-1)
14             {
15                 end=index-1;
16             }
17             else
18             {
19                 start=index+1;
20             }
21             index=partition(input,start,end);
22         }   
23         for(int i=0;i<k;i++)
24         {
25             res.push_back(input[i]);
26         }
27         return res;
28     }
29 
30     int partition(vector<int> &input,int start,int end)
31     {
32         int pivot=input[end];
33         int i=start-1;
34         for(int j=start;j<end;j++)
35         {
36             if(input[j]<=pivot)
37             {
38                 i++;
39                 swap(input[i],input[j]);
40             }
41         }
42         swap(input[i+1],input[end]);
43         return i+1;
44     }
45 };

方法二,就是在博文top k中介绍的方法,开辟大小为k的数组,建立最大堆,然后从n个元素中剩下的任取一个和堆顶元素比较,若小于则更新堆,不小于就不用管。不用改变原数组,时间复杂度为O(nlogk)

另外,值得注意的是:

方法一中使用快排的思想找下标index的过程,最后找到的index所在位置也是数中第K大的数,所以找数组中任意第K大的数的时间复杂度亦为O(n)。

posted @ 2017-08-15 15:09  王大咩的图书馆  阅读(292)  评论(0编辑  收藏  举报