题目描述
输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。
解题思路
本题可以构建一个size为k的最大堆进行求解。
遍历数组。
当堆中元素总量小于k的时候,将当前元素放入堆;
当堆中元素总量等于k的时候,将当前元素与堆顶的元素比较。如果比最大的元素大,淘汰当前元素;如果比对顶元素小,对顶元素出堆,并将当前元素插入堆中。
该算法的空间复杂度为O(k),时间复杂度为O(n)。
代码实现
class Solution {
public:
void maxHeapInsert(vector<int> &maxHeap, int key) {//将插入的元素上调,相当于AdjustUp
//前提是该数组已经符合最大堆的要求了,因此插入一个数之后,要将该数组调整成为最大堆。
maxHeap.push_back(key);
int idx = maxHeap.size()-1;
for (; idx != 1 && key > maxHeap[idx / 2]; idx /= 2) {
maxHeap[idx] = maxHeap[idx / 2];
}
maxHeap[idx] = key;
}
void maxHeapDelete(vector<int> &maxHeap) {//将堆顶的元素向下调整,最后调整成为最大堆。相当于AdjustDown
if (maxHeap.size() == 1) {
return;
}
if (maxHeap.size() == 2) {
maxHeap.pop_back();
return;
}
maxHeap[1] = maxHeap[maxHeap.size() - 1];
maxHeap.pop_back();//用数组中最后的一个元素覆盖最大的元素,然后调整数组使其符合最大堆的定义。
size_t parent = 1, child = 2;
int key = maxHeap[1];
for (; child < maxHeap.size(); child *= 2)
{
if (child + 1 < maxHeap.size() && maxHeap[child] < maxHeap[child + 1])
{
child += 1;
}
if (maxHeap[child] < key) {
break;
}
else {
maxHeap[parent] = maxHeap[child];
parent = child;
}
}
maxHeap[parent] = key;
}
vector<int> GetLeastNumbers_Solution(vector<int> input, int k) {
if(input.size()<k){
return vector<int>();
}
vector<int> maxHeap;//maxHeap是从1开始计数的。
maxHeap.push_back(0);
for (int i = 0; i < input.size(); i++) {
if (maxHeap.size() < k+1) {
maxHeapInsert(maxHeap,input[i]);
}
else if(maxHeap.size()==k+1&&maxHeap[1]>input[i]){
maxHeapDelete(maxHeap);
maxHeapInsert(maxHeap, input[i]);
}
}
//vector<int> res(maxHeap.begin()+1,maxHeap.end());
return vector<int>(maxHeap.begin()+1,maxHeap.end());
}
};