LeetCode——295. Find Median from Data Stream

一.題目連接:ios

  https://leetcode.com/problems/find-median-from-data-streamless

二.題目大意:spa

  給定一段數據流,要求求出數據流中的中位數,其中數據流是動態變化的。若是數據流中的數字個數是奇數的話,則中位數是中間位置的數字;若是數據流中的數字是偶數的話,則中位數是排序好的數據流中的中間兩個數的的平均值。code

三.題解:blog

  若是數據流是靜態不變的話,此時問題是比較好求解的。可是數據流是動態變化的,因此數據流中每次進入一個新的數字時,都要保證可以高效的找到數據流的中位數。咱們能夠這麼考慮:若是把數據流中的數字分爲個數相同的兩部分的話(假設爲A和B,其中A中的數字所有小於B中的數字),那麼咱們所求的中位數,實質就是A中的最大值和B中的最小值的平均值。所以,咱們能夠用兩個堆來表示這個過程,其中大頂堆maxH存儲的是數據流中的數值較小的數字,而小頂堆minH存儲的是數據六中數值較大的數字,且maxH中的數字所有小於minH中的數字。而且堆能夠快速的找出其中的最值,因此能夠快速找獲得minH中的最小值和maxH中的最大值,從而求出中位數。代碼以下:排序

#include<iostream>
#include<unordered_map>
#include<queue>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<sstream>
#include<set>
#include<map>
#include<stack>
#define MAX_NUM 100
using namespace std;
class MedianFinder {
public:
    /** initialize your data structure here. */
    priority_queue<int,vector<int>,less<int>> maxH;//定義大頂堆,用於存儲較小的數據部分
    priority_queue<int,vector<int>,greater<int>> minH;//定義小頂堆,用於存儲較大的數據部分
    MedianFinder() {

    }

    void addNum(int num) {
        maxH.push(num);
        int tmp = maxH.top();
        maxH.pop();
        minH.push(tmp);//保證小頂堆中的數據大於大頂堆中的數據
        if(minH.size() > maxH.size())
        {
            int tmp = minH.top();
            minH.pop();
            maxH.push(tmp);//保證大頂堆中的數據小於小頂堆中的數據
        }

    }

    double findMedian() {
        if(minH.size() == maxH.size())//若是兩個堆的大小相同,則返回它們最值的平均值
            return (minH.top() + maxH.top()) / 2.0;
        return minH.size() > maxH.size() ? minH.top() : maxH.top();//若是兩個堆的大小不相同,返回數字個數多的堆的最值
    }
};

/**
 * Your MedianFinder object will be instantiated and called as such:
 * MedianFinder obj = new MedianFinder();
 * obj.addNum(num);
 * double param_2 = obj.findMedian();
 */


int main()
{
    MedianFinder test = MedianFinder();
    test.addNum(1);
    test.addNum(2);
    test.addNum(3);
    test.addNum(4);
    test.addNum(5);
    cout<<test.findMedian()<<endl;


}

每次從數據流中找出中位數的時間爲O(1),調整兩個堆的時間爲O(logN),對於含有n個數字的數據流,總的時間複雜度爲O(NlogN),空間複雜度爲O(N)。隊列

此外,有幾個點須要注意下:leetcode

1.代碼中使用了priority_queue即優先隊列來實現堆,由於優先隊列獲取優先級最高的值所需時間爲O(1),調整的過程爲O(logN),與堆的操做時間相似,能較好的模擬堆。get

2.一般狀況下,堆默認的優先級最高的值是指的最大值,也能夠是最小值,不過須要顯式的說明(見本例中優先隊列的定義)。string

3.要保證最小堆中存儲的始終是較大的數值,而大頂堆中存儲的是較小的數值。因此纔會有addNum中的那些操做。

相關文章
相關標籤/搜索