1. 程式人生 > >[leetcode]295. Find Median from Data Stream數據流的中位數

[leetcode]295. Find Median from Data Stream數據流的中位數

and for pri img 分享 void 平衡 per AS

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.

For example,

[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.

Example:

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

題意:

給定一堆數據,求其中位數(將數據升序排列。若數據個數為奇,則正中為中位數;若數據個數為偶,則正中兩數平均值為中位數)

思路:

顯然若數據大,排序再找中位數是不現實的。

用PriorityQueue分別建maxHeap, minHeap, 並保證maxHeap.size() - minHeap.size() <=1

如此,當最終maxHeap.size() = minHeap.size() 說明數據個數為偶,取兩個Heap的peek值的平均值

當最終maxHeap.size() > minHeap.size() 說明數據個數為奇,取maxHeap.peek

掃數據中的每個元素

[6,  10,  2,  6,  5,  0,  6,  3]

^ 若maxHeap.isEmpty() || 當前元素 < maxHeap.peek() , 扔到maxHeap裏去

技術分享圖片

[6,  10,  2,  6,  5,  0,  6,  3]

^ 若當前元素 >= maxHeap.peek() , 扔到minHeap裏去

技術分享圖片

[6,  10,  2,  6,  5,  0,  6,  3]

^ 當前元素 < maxHeap.peek() , 扔到maxHeap裏去

技術分享圖片

[6,  10,  2,  6,  5,  0,  6,  3]

^ 若當前元素 >= maxHeap.peek() , 扔到minHeap裏去,minHeap會自動將內部最小值sort到peek位置

技術分享圖片

[6,  10,  2,  6,  5,  0,  6,  3]

^ 當前元素 < maxHeap.peek() , 扔到maxHeap裏去

此時maxHeap.size() - minHeap.size() = 2 需要維護平衡

技術分享圖片

將maxHeap.peek加到minHeap上來,則變成

技術分享圖片

......

如此以往,直至掃完整個數據。

代碼:

 1 class MedianFinder {
 2 
 3     /** initialize your data structure here. */
 4     private PriorityQueue<Integer> _maxHeap; 
 5     private PriorityQueue<Integer>  _minHeap;
 6 
 7     public MedianFinder() {
 8         _maxHeap = new  PriorityQueue<> ((o1,o2) -> o2-o1); 
 9         _minHeap = new  PriorityQueue<> ((o1,o2) -> o1-o2); 
10     }
11     
12     public void addNum(int num) {
13         // put each integer into either maxHeap or minHeap
14         if(_maxHeap.isEmpty() || num < _maxHeap.peek()){
15             _maxHeap.add(num);
16         } else{
17             _minHeap.add(num);
18         }
19         // keep balance 
20         if(_maxHeap.size() ==_minHeap.size()+2){
21             _minHeap.add(_maxHeap.poll());
22         }
23         
24           if(_minHeap.size() ==_maxHeap.size()+1){
25             _maxHeap.add(_minHeap.poll());
26         }
27         
28     }
29     // the number of data is even or odd 
30     public double findMedian() {
31         if (_maxHeap.size() == _minHeap.size()) {
32             return (_maxHeap.peek() + _minHeap.peek()) /  2.0;
33         }else {
34             return _maxHeap.peek();
35         }
36     }       
37 }
38 
39 /**
40  * Your MedianFinder object will be instantiated and called as such:
41  * MedianFinder obj = new MedianFinder();
42  * obj.addNum(num);
43  * double param_2 = obj.findMedian();
44  */

[leetcode]295. Find Median from Data Stream數據流的中位數