leetcode hot100 堆

如有缺漏谬误,还请批评指正。

1.第k大的元素 

(1)建堆:从最后一个非叶子结点开始建大根堆,建堆时递归调整。

核心操作:如果某个孩子比当前节点大,则交换它们,并递归建堆操作(因为此时被交换的结点可能不满足大根堆的性质)。

(2)找第k大的元素:从堆尾元素开始一个个弹出并调整堆,弹出k-1次后,堆顶元素就是第k大的元素。

class Solution {
public:
    void maxHeapify(vector& a,int i,int heapSize){
        int l=i*2+1,r=i*2+2,largest=i;
        if(la[largest]) largest=l;
        if(ra[largest]) largest=r;
        if(largest!=i){
            swap(a[i],a[largest]);
            maxHeapify(a,largest,heapSize);
        }
    }
    void buildMax(vector& nums,int heapSize){
        for(int i=heapSize/2-1;i>=0;i--){
            maxHeapify(nums,i,heapSize);
        }
    }
    int findKthLargest(vector& nums, int k) {
        int heapSize=nums.size();
        buildMax(nums,heapSize);
        for(int i=nums.size()-1;i>=nums.size()-k+1;i--){
            swap(nums[0],nums[i]);
            heapSize--;
            maxHeapify(nums,0,heapSize);
        }
        return nums[0];
    }
};

2.前k个高频元素

(1)堆里已有k个元素:比较当前元素和堆顶元素(堆中元素的最小值),若当前元素大于堆顶元素,则弹出堆顶元素,并把当前元素放入堆中。

(2)堆里元素还不满k个:直接把当前元素放入堆中。

class Solution {
public:
    static bool cmp(pair& m,pair& n){
        return m.second>n.second;
    }
    vector topKFrequent(vector& nums, int k) {
        unordered_map occurrences;
        for(auto& v:nums) occurrences[v]++;
        priority_queue,vector>,decltype(&cmp)> q(cmp);
        for(auto &[num,cnt]:occurrences){
            if(q.size()==k){
                if(q.top().second res;
        while(q.size()){
            res.push_back(q.top().first);
            q.pop();
        }
        return res;
    }
};

3.数据流的中位数

使用两个堆(优先队列)来维护数据:
  • queMin:最大堆(使用 less 比较器),存储数据流中较小的一半数字

  • queMax:最小堆(使用 greater 比较器),存储数据流中较大的一半数字

算法流程:

(1)判断新数字应加入哪个堆

①如果queMin为空,或num<=queMin的堆顶(小于等于较小一半数字的最大值),则加入queMin

②否则加入queMax

(2)平衡两个堆的大小

①如果加入queMin后queMin的大小比queMax大2个以上,则将queMin的堆顶移到queMax

②如果加入queMax后queMax的大小比queMin大,则将queMax的堆顶移到queMin

结果输出:

(1)如果 queMin 的大小 > queMax 的大小(总数为奇数):中位数就是 queMin 的堆顶

(2)否则(总数为偶数):中位数是 queMin 堆顶和 queMax 堆顶的平均值

class MedianFinder {
public:
    priority_queue,less> queMin;
    priority_queue,greater> queMax;
    MedianFinder(){}
    void addNum(int num){
        if (queMin.empty()||num<=queMin.top()) {
            queMin.push(num);
            if (queMax.size()+1queMin.size()) {
                queMin.push(queMax.top());
                queMax.pop();
            }
        }
    }
    double findMedian() {
        if(queMin.size()>queMax.size()) return queMin.top();
        return (queMin.top()+queMax.top())/2.0;
    }
};

 

 

你可能感兴趣的:(算法,leetcode,数据结构)