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

来源:互联网 发布:linux下目录重命名 编辑:程序博客网 时间:2024/05/18 01:36

一:题目描述

输入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());                 }};
必须学会,很多面试题都考这个!!!
 
原创粉丝点击