剑指offer29题:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
首先必须注意的一点是:这道题不是考察数组的排序(所以解法1不推荐),如果N特别大的话,内存存不下;这道题正确解法是:找一个数据结构存储这K个数,如果后面的数大于这K个数的最大值,则把这个数和最大值替换。
解法一:
//解法一:自己写的,冒泡排序
//自己写的这个好像不是冒泡排序,有点像选择排序。。。。
// vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
// vector<int> result;
// if(input.empty() || k==0 || k>input.size())
// {
// return result;
// }
// //int min = input[0];
// for(int i=0;i<input.size();i++)
// {
// for(int j=i+1;j<input.size();j++)
// {
// if(input[j]<input[i])
// {
// int temp;
// temp = input[i];
// input[i] = input[j];
// input[j] = temp;
// }
// }
// }
// for(int i=0;i<k;i++)
// {
// result.push_back(input[i]);
// }
// return result;
// }解法2:
//解法二:牛客大佬写的,用最大堆实现,堆的大小为K,不过调用了algorithml里的make_heap这些现成的函数
//注意和解法四的区别
// vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
// {
// if(input.empty() || k==0 || k>input.size())
// {
// return vector<int>{};
// }
// vector<int> result(input.begin(),input.begin()+k);
// make_heap(result.begin(),result.end());//建立最大堆
// for(int i=k;i<input.size();i++)
// {
// if(result[0]>input[i])
// {
// pop_heap(result.begin(),result.end());//把最大值移到最后一个元素
// result.pop_back(); //移除最后一个元素
// result.push_back(input[i]);
// push_heap(result.begin(),result.end()); //重新选出最大值
// }
// }
// sort_heap(result.begin(),result.end());
// return result;
// }解法3:
//解法三:牛客大佬写的,利用自动排序的set这个数据结构,set大小为K,时间复杂度O(nlogk)
//不能直接修改set容器内数据,所以只能删除某元素再插入要修改的数值。
// vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
// {
// if(input.empty() || k==0 || k>input.size())
// {
// return vector<int>{};
// }
// //仿函数中的greater<T>模板,从大到小排序,首元素为最大值
// multiset<int, greater<int> > leastNums;
// vector<int>::iterator vec_it=input.begin();
// for(;vec_it!=input.end();vec_it++)
// {
// //将前k个元素插入集合
// if(leastNums.size()<k)
// leastNums.insert(*vec_it);//插入这个元素,插入时候就排好序了!!!!!!!1
// else
// {
// //第一个元素是最大值
// multiset<int, greater<int> >::iterator greatest_it=leastNums.begin();
// //如果后续元素<第一个元素,删除第一个,加入当前元素
// if(*vec_it<*(leastNums.begin()))
// {
// leastNums.erase(greatest_it);//删除首元素
// leastNums.insert(*vec_it);//插入这个元素,插入时候就排好序了!!!!!!!1
// }
// }
// }
// return vector<int>(leastNums.begin(),leastNums.end());
// }解法4:
//解法四:牛客大佬写的,也是最大堆实现,不过没有用algorithm里的make_heap,而是自己y用vector实现最大堆并排序
vector<int> GetLeastNumbers_Solution(vector<int> input, int k)
{
if(input.empty() || k==0 || k>input.size())
{
return vector<int>{};
}
vector<int> result;
for(int i=input.size()/2-1;i>=0;i--)//建立堆
{
adjustHeap(input,i,k); //堆的大小为k
}
for(int i=k;i<input.size();i++)//将后面的数依次和K个数的最大值比较
{
if(input[0]>input[i])
{
int temp=input[i];
input[i]=input[0];
input[0]=temp;
adjustHeap(input,0,k);
}
}
for(int i=0;i<k;i++)
{
result.push_back(input[i]);
}
return result;
}
void adjustHeap(vector<int>&input,int i,int n)//堆调整 n为length
{
int left = 2*i+1; // i节点的左孩子
int right = 2*i+2; // i节点的右孩子
int largest = i; //先设置父节点和子节点三个节点中最大值的位置为父节点下标
if(left<n&&input[left]>input[largest])
{
largest = left;
}
if(right<n&&input[right]>input[largest])
{
largest = right;
}
if(largest!=i) //最大值不是父节点,则进行交换
{
int temp;
temp = input[i];
input[i] = input[largest];
input[largest] = temp;
adjustHeap(input,largest,n); //递归调用,保证子树也是最大堆
}
}
void heapSort(vector<int>&input,int length) //堆排序 这里没用到
{
for(int i=length/2-1;i>=0;i--)
{//初始化堆
adjustHeap(input,i,length);
}
for(int i=length-1;i>0;i--)
{
int temp=input[i];
input[i]=input[0];
input[0]=temp;
adjustHeap(input,0,i);
}
}
};
京公网安备 11010502036488号