Leetcode 295. Find Median from Data Stream

Problem:

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

 

Follow up:

  1. If all integer numbers from the stream are between 0 and 100, how would you optimize it?
  2. If 99% of all integer numbers from the stream are between 0 and 100, how would you optimize it?

 

Solution:

  这道题要我们在数据流中找出中值,用数组的话插入的时间复杂度就是线性的,用set或二叉搜索树又不能做到随机查询,看了这道题的标签有个Heap我才知道用优先级队列。这里用一个大顶堆small和小顶堆large,大顶堆里是小于中位数的所有数字,小顶堆里是大于中位数的所有数字,并且我们确保大顶堆的元素个数只比小顶堆多1或相等。这样如果两个堆元素个数相等,就取堆顶取平均,否则取small的堆顶。对于follow up1,我们可以使用counting sort,用一个数组记录0到100元素出现的个数,每次插入把计数器加1,这样是O(1)的插入效率,查询时只需找到中间值在哪个元素上即可,查询效率也是O(1)。对于follow up2,我们则使用counting sort加优先级队列即可,是原问题和follow up1的结合。

Code:

 

 1 class MedianFinder {
 2 public:
 3     struct mycompare{
 4         bool operator()(int &a,int &b){
 5             return a>b;
 6         }
 7     };
 8     /** initialize your data structure here. */
 9     MedianFinder() {
10         
11     }
12     
13     void addNum(int num) {
14         if(small.empty()){
15             small.push(num);
16             return;
17         }
18         if(small.size() == large.size()){
19             if(num >= large.top()){
20                 small.push(large.top());
21                 large.pop();
22                 large.push(num);
23             }
24             else
25                 small.push(num);
26         }
27         else{
28             if(num <= small.top()){
29                 large.push(small.top());
30                 small.pop();
31                 small.push(num);
32             }
33             else
34                 large.push(num);
35         }
36     }
37     
38     double findMedian() {
39         if(small.size() == large.size())
40             return (small.top()+large.top())/2.0;
41         else
42             return small.top();
43     }
44 private:
45     priority_queue<int> small;
46     priority_queue<int,vector<int>,mycompare> large;
47 };
48 
49 /**
50  * Your MedianFinder object will be instantiated and called as such:
51  * MedianFinder obj = new MedianFinder();
52  * obj.addNum(num);
53  * double param_2 = obj.findMedian();
54  */

 

posted on 2019-01-10 06:26  周浩炜  阅读(526)  评论(0编辑  收藏  举报

导航