牛客网《剑指Offer》编程 29. 最小的k个元素 (使用堆)

题目描述

输入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());
}
};

猜你喜欢

转载自blog.csdn.net/eriHanami/article/details/82954654