295. Find Median from Data Stream

Description

Median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value. So the median is the mean of the two middle value.

Examples:

[2,3,4] , the median is 3

[2,3], the median is (2 + 3) / 2 = 2.5

Design a data structure that supports the following two operations:

  • void addNum(int num) - Add a integer number from the data stream to the data structure.
  • double findMedian() - Return the median of all elements so far.

For example:

addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2

Credits:
Special thanks to @Louis1992 for adding this problem and creating all test cases.

Solution

Insertion sort, addNum time O(n), findMedian time O(1) (TLE)

Two heaps, addNum time O(log n), findMedia time O(1)

维护两个heap,lo为maxHeap,存储small half。hi为minHeap,存储large half。

Adding a number num:

  • Add num to max-heap lo. Since lo received a new element, we must do a balancing step for hi. So remove the largest element from lo and offer it to hi.
  • The min-heap hi might end holding more elements than the max-heap lo, after the previous operation. We fix that by removing the smallest element from hi and offering it to lo.

The above step ensures that we do not disturb the nice little size property we just mentioned.

注意:

  • 每次addNum时,先将其添加到maxHeap中,然后无脑将maxHeap的顶端元素取出放到minHeap中,否则maxHeap中会有大于minHeap的元素存在。
  • 然后再一次调整堆,保证maxHeap的元素数量不小于minHeap的。
class MedianFinder {
    private PriorityQueue maxHeap; // store small half values
    private PriorityQueue minHeap; // store big half values
    
    /** initialize your data structure here. */
    public MedianFinder() {
        maxHeap = new PriorityQueue<>((a, b) -> b - a);
        minHeap = new PriorityQueue<>();
    }
    
    public void addNum(int num) {
        maxHeap.offer(num);  // adjust every time
        minHeap.offer(maxHeap.poll());
        
        if (maxHeap.size() < minHeap.size()) {  // important to adjust again
            maxHeap.offer(minHeap.poll());
        }
    }
    
    public double findMedian() {
        return maxHeap.size() == minHeap.size()
            ? 0.5 * (maxHeap.peek() + minHeap.peek()) : maxHeap.peek();
    }
}

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

你可能感兴趣的:(295. Find Median from Data Stream)