堆结构的应用--Leecode刷题

我记得以前做题就经常碰到堆,但是也没有记录过什么,今天决定记录一下堆的应用!

1.找中位数

295. 数据流的中位数

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[2,3,4] 的中位数是 3

[2,3] 的中位数是 (2 + 3) / 2 = 2.5

设计一个支持以下两种操作的数据结构:

void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。

示例:
addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2

这道题就是所谓的添加元素,然后找中位数,这题我开始用的是List 加 lower_bound()结果后来超时,后来看了题解用堆确实是好方法!!!

1.你需要维护两个堆:
priority_queue<int,vector,less> low; (大顶堆)
priority_queue<int,vector,greater> up;(小顶堆)

一个堆用来存放一半小数字(low),一半大数字(up).
如图(红色是low堆的值,蓝色应该是up堆的值)

之后变成堆的结构应该如下图:
在这里插入图片描述

其实很容易看出来,如果为单数,取的就是大顶堆(low)的顶,若为偶数,就取大顶堆和小顶堆顶和除2!

2.关于添加数字。如何添加,若添加的数字num大于up顶的值,很明显,应该添加到up里面,其他情况添加到low里面。之后保证low中的值永远大于up的值+1或者数量相等,适当的把两者的top值移动,保持上述条件即可。
代码如下

class MedianFinder {
public:
    /** initialize your data structure here. */
    priority_queue<int,vector<int>,less<int>> low;
    priority_queue<int,vector<int>,greater<int>> up;
   
    MedianFinder() {

    }

    void addNum(int num) {

       if(!up.empty()&&num > up.top()) up.push(num);
       else low.push(num);

       if(low.size() > up.size()+1){
           up.push(low.top());
           low.pop();
       }

       if(low.size() < up.size()){
           low.push(up.top());
           up.pop();
       }
    }

    double findMedian() {
       if(low.size() > up.size()) return double(low.top());
       else return double(low.top()+up.top())/2;
    }
};

(图片借用了Leecode)

未完待续…

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章