堆相关知识:
堆可以分为最大堆(最小堆),两者取最大(最小)时间复杂度为O(1),插入新的元素或删除元素,调整的时间复杂度均为O(log(n))
这里面要注意最大堆(最小堆)的左右子树仍为最大堆(最小堆)
堆的库使用:
堆在C++中实现该数据结构的实际就是优先队列
优先队列
- #include < queue>
实现一
简要说一下思想就是,将所有数据压入优先级队列中,要第k大的元素,就先把之前k-1个元素弹出,取栈顶就是要的第k大的元素
#include <iostream>
#include <queue>
using namespace std;
class Solution {
public:
int findKthLargest(vector<int>& nums, int k) {
priority_queue<int> q;
for (int i = 0;i < nums.size();i++) {
q.push(nums[i]);
}
for (int i = 1;i < k;i++) {
q.pop();
}
return q.top();
}
};
库真好用,1分钟解一道题
实现一的评价与思考
我这种实现虽然比较简单,但难免每次都需要进行新的计算,而且维护的堆的大小是始终增加的,但n规模较小的时候还可以,但当n比较大的时候,调整堆还是比较耗时的,这种方法不仅耗时还耗空间
实现二
实现思想
由于要第k个大的元素,可以只维护一个大小为k的最小堆,但其实这个k个元素的堆里面放的是前k个最大的元素,由于题中要第k大的元素,这个元素在维护的这个堆中其实是最小的。
- 具体流程
- 维护的堆元素小于k,新来的元素直接压入,否则按下列的规则进行
- 新来的元素大于栈顶元素,栈顶元素弹出,压入新来的元素
- 新来的元素小于栈顶元素,不作处理
时间复杂度
在LeetCode215中找第k大的数时,最原始的想法肯定是先排个序,然后再第K大的数据,那么时间复杂度为O(nlog(n))当n和K相差的比较多的情况下O(nlog(n))要比O(nlog(k))大很多,在这种实现的方式下,维护的堆大小为k,那么时间复杂度为O(nlog(k))