剑指offer面试题40--最小的k个数

题目描述:

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

设计思想一:

创建一个结果容器,若放源数据的容器的源数据的个数少于k个,则把所有源数据直接插入结果容器,若源容器的数据数目多于k个,则取完k个后,以后取出的每个元素都要和结果容器的元素最大值比,若比结果容器的最大值大,则该元素替换结果容器的最大值,否则,取源容器的下一个数据。

因此容器元素数目够k个后,做三件事:1.在k个数里找最大数。2.删除原最大数。3.将新元素插入结果容器。

可在O(logk)时间内完成这三件。又由于有n个源数据,所以总的时间复杂度O(nlogk)

此法优势在于不修改输入数组,适合处理大量数据

class Solution {
public:
    multiset<int,greater<int> > LeastNums;
    multiset<int,greater<int> >::iterator it;
    
    void GetLeastNums(vector<int> input,int k)
     {
         int i=0;
          for(i=0;i<k;++i)
              LeastNums.insert(input[i]);
         
       int length=input.size();
         if(length>k)
         {
             while(i!=length)  
             {
                  if(input[i]<*(LeastNums.begin()))
                  {
                      LeastNums.erase(LeastNums.begin());
                      LeastNums.insert(input[i]);
                      
                  }
                     ++i;
             }
         }
     }
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) 
    {
        if(input.size()<k)
            return {};
        vector<int> Vec;
         GetLeastNums(input,k);
        for(it=LeastNums.begin();it!=LeastNums.end();++it)
        {
             Vec.push_back(*it);
        }
         return Vec;
    }
};

设计思想二:

从面试题39“数组中出现次数超过一半的数字”取得启发,此题也用Partition()。能否调整到:某数左边是比它小的k-1个数,该数右边的数比它都大?时间复杂度是O(n)

这种方法需要修改输入数组,如果面试官要求不能修改输入数组,则不能用此法

#include <algorithm>
#define random(a,b) (rand()%(b-a+1)+a)

class Solution {
public:
    
    int Partition(vector<int>& data, int length, int start, int end)
    //vector<int>& data必须加引用,因为后期用的就是在Partition函数中改变的容器data
  {
     int pivot = random(start, end);
    swap(data[pivot], data[end]);
        int small = start - 1;
    for (int index = start; index<end; index++)
    {
        //如果index所指向的元素小于pivot枢纽元素的话,index和small游标一起向右走,当index所指向的元素大于或者等于pivot枢纽元素的话,只是index自己向右走,small不动,这样的话index走啊走啊 发现有一个小于pivot枢纽元素的时候,将此元素与small所指向的元素互换
        if (data[index]<data[end])//此处若改成大于号则从大到小排
        {
            ++small;
            if (small != index)
            {
                swap(data[index], data[small]);
            }
            
        }
        
    }
    ++small;
    //最后把small所指向元素与枢纽元素pivot互换
    swap(data[small], data[end]);
         return small;

}


    vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
    {
        vector<int> output;
        int n=input.size();
        if(n==0||k<=0||k>n)
            return {};
        int start = 0;
        
    int end = n - 1;
    int index = Partition(input, n, start, end);
    while(index != k - 1)
    {
        if(index > k - 1)
        {
            end = index - 1;
            index = Partition(input, n, start, end);
        }
        else
        {
            start = index + 1;
            index = Partition(input, n, start, end);
        }
    }

        
        for(int i=0;i<k;++i)
            output.push_back(input[i]);
        
        return output;
        
        
    }
};
扫描二维码关注公众号,回复: 2580145 查看本文章

猜你喜欢

转载自blog.csdn.net/qq_34793133/article/details/81257854
今日推荐