【剑指Offer】面试题30:最小的k个数

一:题目描述

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

二:解题思路

方法一:直接对数组中的元素进行排序,输出前k个元素

class Solution {
public:
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
         
        vector<int> res;
        if(input.empty() || k>input.size())
            return res;
        sort(input.begin(),input.end());
        int i;
        for(i=0;i<k;i++)
            res.push_back(input[i]);
         
        return res;
 
 
 
    }
};

方法2:基于面试题29的思想(时间复杂度最小  O(n))

基于数组第k个数来调整,使得比第k个数小的所有数都位于数组的左边,比他大的数都位于数组的右面

class Solution {
public:
    
    void Swap(vector<int> &numbers,int i,int j){
        int temp=numbers[i];
        numbers[i]=numbers[j];
        numbers[j]=temp;
    }
     
    int Partition(vector<int> &numbers,int start,int end){
        if(numbers.size()<=0 || start<0 || end>numbers.size()-1)
            return;
        int index=start; 
       //在start与end范围内随机产生一个数  如果number[index]在数组中从小到大排序第k名,则在返回时,返回k-1(下标从0开始),更新后的数组,坐标小于k-1的元素值都小于等于number[index],下标大于k-1的元素值都大于等于number[index]
         
        Swap(numbers,index,end);
         
        int small=start-1;
         
        for(index=start;index<end;index++){
            if(numbers[index]<numbers[end]){
                small++;
                if(small!=index)
                    Swap(numbers,index,small);
            }
        }
        small++;
        Swap(numbers,small,end);
         
        return small;
    }
    

    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
   
     
        //判断输入数组是否有效
        vector<int> result;
        if(input.size()<=0 || input.size()<k || k<1)
            return result;
         
        //随机快排算法的思想  
        int start=0;
        int end=input.size()-1;
         
        int index=Partition(input,start,end);
        while(index!=(k-1)){
            if(index<k-1){
                start=index+1;
                index=Partition(input,start,end);
            }
            else{
                end=index-1;
                index=Partition(input,start,end);
            }
        }
        
        for(int i=0;i<k;i++)
            result.push_back(input[i]);
        return result;
             
    }
};
方法3:利用STL容器(时间复杂度O(nlogk)),适合海量数据,不改变原数组的值
创建大小为k的数据容器存放最小的k个数
如果当前容器已有的数字小于k个数,则直接将这次读入的整数放入容器中
如果容器的已经有了K个数,也就是容器满了,则找到容器中最大的数比较,大于,抛弃当前这个数,否则,替代容器中最大的数
 
 
因此在容器满后,我们需要做三件事:
1.在k个数中找到最大值
2.可能在这个容器中删除最大值
3.可能插入一个新值
 
排序和插入可以使用STL现有的方法实现
 
 
class Solution {
public:
    
    vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
   		int len=input.size();
        if(len<=0  || len<k || k<=0)
            return vector<int>();
        
        //仿函数中的greater<T>模板,从大到小排序
        multiset<int,greater<int>> leastNums;
        multiset不提供直接存取元素的任何函数操作,通过iterator 进行元素存取
        vector<int>::iterator vec_it=input.begin();
        for(;vec_it!=input.end();vec_it++){
            
            //将前k个元素插入集合
            if(leastNums.size()<k)
                leastNums.insert(*vec_it);
            else{
                
                //第一个元素是最大值
                multiset<int,greater<int>>::iterator greater_it=leastNums.begin();
                if(*vec_it<*(leastNums.begin())){
                    leastNums.erase(greater_it); //注意这步
                    leastNums.insert(*vec_it);
                }
            }
        }
     return vector<int>(leastNums.begin(),leastNums.end());
             
    }
};

必须学会,很多面试题都考这个!!!
 
 

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值