295 Find Median from Data Stream 數據流的中位數

中位數是排序後列表的中間值。若是列表的大小是偶數,則沒有中間值,此時中位數是中間兩個數的平均值。
示例:
[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
詳見:https://leetcode.com/problems/find-median-from-data-stream/description/html

Java實現:java

參考:https://www.cnblogs.com/Liok3187/p/4928667.html數據結構

O(nlogn)的作法是開兩個堆(java用優先隊列代替)。
最小堆放小於中位數的一半,最大堆放較大的另外一半。
addNum操做,把當前的num放到size小的堆中,經過2次poll-add操做,保證了最小堆中的全部數都小於最大堆中的數。
findMedian操做,若是size不一樣,就是其中一個堆頂,不然就是連個堆頂的數相加除以2。less

class MedianFinder {
    private Queue<Integer> maxHeap;
    private Queue<Integer> minHeap;

    /**
     * initialize your data structure here.
     */
    public MedianFinder() {
        this.maxHeap = new PriorityQueue<Integer>(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2.compareTo(o1);
            }
        });
        this.minHeap = new PriorityQueue<Integer>();
    }

    public void addNum(int num) {
        if (maxHeap.size() < minHeap.size()) {
            maxHeap.add(num);
            minHeap.add(maxHeap.poll());
            maxHeap.add(minHeap.poll());
        } else {
            minHeap.add(num);
            maxHeap.add(minHeap.poll());
            minHeap.add(maxHeap.poll());
        }
    }

    public double findMedian() {
        if (maxHeap.size() < minHeap.size()) {
            return minHeap.peek();
        } else if (maxHeap.size() > minHeap.size()) {
            return maxHeap.peek();
        } else {
            return (minHeap.peek() + maxHeap.peek()) / 2.0;
        }
    }
}

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

C++實現:ide

方法一:this

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder() {
        maxH={};
        minH={};
    }
    
    void addNum(int num) {
        if(((minH.size() + maxH.size()) & 0x1) == 0)
        {
            if(!maxH.empty() && num<maxH[0])
            {
                maxH.push_back(num);
                push_heap(maxH.begin(),maxH.end(),less<int>());

                num = maxH[0];
                pop_heap(maxH.begin(),maxH.end(),less<int>());
                maxH.pop_back();
            }
            minH.push_back(num);
            push_heap(minH.begin(),minH.end(),greater<int>());

        }
        else
        {
            if(!minH.empty() && num>minH[0])
            {
                minH.push_back(num);
                push_heap(minH.begin(),minH.end(),greater<int>());

                num = minH[0];
                pop_heap(minH.begin(),minH.end(),greater<int>());
                minH.pop_back();
            }
            maxH.push_back(num);
            push_heap(maxH.begin(),maxH.end(),less<int>());
        }

    }
    
    double findMedian() {
        int size = minH.size() + maxH.size();

        double median = 0;
        if((size&0x1) == 1)
        {
            median = minH[0];
        }
        else
        {
            median = (minH[0]+maxH[0])*0.5;
        }
        return median;
    }
private:
    vector<int> maxH;
    vector<int> minH;
};

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

 方法二:.net

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder() {
        
    }
    
    void addNum(int num) {
        small.push(num);
        large.push(-small.top());
        small.pop();
        if(small.size()<large.size())
        {
            small.push(-large.top());
            large.pop();
        }
    }
    
    double findMedian() {
        return small.size()>large.size()?small.top():0.5*(small.top()-large.top());
    }
private:
    priority_queue<int> small,large;
};

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

方法三:設計

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder() {
        
    }
    
    void addNum(int num) {
        small.insert(num);
        large.insert(-*small.begin());
        small.erase(small.begin());
        if(small.size()<large.size())
        {
            small.insert(-*large.begin());
            large.erase(large.begin());
        }
    }
    
    double findMedian() {
        return small.size()>large.size()?*small.begin():0.5*(*small.begin()-*large.begin());
    }
private:
    multiset<int> small,large;
};

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

 方法四:code

class MedianFinder {
public:
    /** initialize your data structure here. */
    MedianFinder() {
        
    }
    
    void addNum(int num) {
        if(maxH.empty()||num<=maxH.top())
        {
            maxH.push(num);
        }
        else
        {
            minH.push(num);
        }
        if(minH.size()+2==maxH.size())
        {
            minH.push(maxH.top());
            maxH.pop();
        }
        if(maxH.size()+1==minH.size())
        {
            maxH.push(minH.top());
            minH.pop();
        }
    }
    
    double findMedian() {
        return minH.size()==maxH.size()?0.5*(minH.top()+maxH.top()):maxH.top();
    }
private:
    priority_queue<int,vector<int>,less<int>> maxH;
    priority_queue<int,vector<int>,greater<int>> minH;
};

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

 參考:https://blog.csdn.net/sjt19910311/article/details/50883735htm

https://www.cnblogs.com/grandyang/p/4896673.html

相關文章
相關標籤/搜索