一:题目描述
输入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());
}
};
必须学会,很多面试题都考这个!!!