数据流中的中位数

你快乐吗?

Posted by bbkgl on October 27, 2019

深知身在情长在

怅望江头江水声

C++,最大堆,最小堆。

一开始想到的是直接用一个数组或者vector存储,插入的时候顺序查找并计数,然后Insert是O(n),GetMedian是O(1),但是觉得太简单了,肯定不是这样的,慢慢就想到能不能一半大,一半小,于是就想到了堆。

在插入的时候,把大的一半放到最小堆,把大的一半放到最大堆,而插入堆的复杂度是O(logn),应该就欧科了。当然插入元素X的操作需要遵循以下规则:

  • 如果两个堆都为空,将X插入最大堆
  • 如果两个堆元素个数相等,分以下两种情况:
    • 如果元素X大于最小堆的堆顶,则弹出最小堆堆顶,将堆顶元素插入最大堆,将元素X插入最小堆
    • 否则直接将X插入最大堆
  • 如果两个堆元素不等,则最大堆一定多一个元素:
    • 如果元素X小于最大堆的堆顶,则弹出最大堆堆顶,将堆顶元素插入最小堆,将元素X插入最大堆
    • 否则直接将X插入最小堆

GetMedian操作直接判断奇偶就哦科了!

class Solution {
public:
    void pushh(vector<int> &heap, int num, int flag) {
        heap.push_back(num);
        if (flag == 1) // 小顶堆
            push_heap(heap.begin(), heap.end(), less<int>());
        else
            push_heap(heap.begin(), heap.end(), greater<int>());
    }
    
    int poph(vector<int> &heap, int flag) {
        if (flag == 1)
            pop_heap(heap.begin(), heap.end(), less<int>());
        else
            pop_heap(heap.begin(), heap.end(), greater<int>());
        int rnum = heap.back();
        heap.pop_back();
        return rnum;
    }
    
    void Insert(int num) {
        if (max_heap.size() == min_heap.size()) {
            if (max_heap.empty() || num < max_heap.front())
                pushh(max_heap, num, 1);
            else {
                if (min_heap.front() < num) {
                    int pop_num = poph(min_heap, -1);
                    pushh(max_heap, pop_num, 1);
                    pushh(min_heap, num, -1);
                } else 
                    pushh(max_heap, num, 1);
            }
        } else {
            if (num < max_heap.front()) {
                int pop_num = poph(max_heap, 1);
                pushh(max_heap, num, 1);
                pushh(min_heap, pop_num, -1);
            } else 
                pushh(min_heap, num, -1);
        }
    }

    double GetMedian() { 
        if (min_heap.size() == max_heap.size())
            return static_cast<double>(min_heap.front() + max_heap.front()) / 2.0;
        else
            return static_cast<double>(max_heap.front());
    }
    
private:
    vector<int> max_heap;
    vector<int> min_heap;
};