堆的基础知识:
入堆push,复杂度O(logn)
出堆pop,复杂度O(1)
常见算法应用:
1.数组第k大元素;
2.查找中位数
1.求数组第k大元素
class Solution { public: int findKthLargest(vector<int>& nums, int k) { priority_queue<int,vector<int>,greater<int>> max(nums.begin(),nums.begin()+k); //维护一个最小堆,前k个值初始化为数组前k个值 int len=nums.size(); for(int i=k;i<len;i++){ //注意从k开始,因为前面的已经入堆 if(nums[i]>max.top()){ //若大于对顶则pop出堆顶,将当前数组元素入堆 max.pop(); max.push(nums[i]); } } return max.top(); //直接去堆顶即为第k大元素 } };
用快排时间复杂度O(nlogn),这里用堆。由于堆规模最大为k,故每次push复杂度O(logk),n次为O(nlogk),优于快排。
2.中位数
class MedianFinder { public: /** initialize your data structure here. */ MedianFinder() { } void addNum(int num) { if(max.empty()){ max.push(num); return; } if(max.size()<=min.size()){ if(num<=min.top()){ max.push(num); }else{ max.push(min.top()); min.pop(); min.push(num); } }else{ if(num<=max.top()){ min.push(max.top()); max.pop(); max.push(num); }else{ min.push(num); } } } double findMedian() { if(max.empty() && min.empty()) return 0; else if(max.size()==min.size()) return (double)(max.top()+min.top())/2;//注意转化为double else return max.size()>min.size()?max.top():min.top(); } private: priority_queue<int> max; priority_queue<int,vector<int>,std::greater<int> > min; }; /** * Your MedianFinder object will be instantiated and called as such: * MedianFinder obj = new MedianFinder(); * obj.addNum(num); * double param_2 = obj.findMedian(); */