码迷,mamicode.com
首页 > 其他好文 > 详细

295. Find Median from Data Stream

时间:2021-04-16 11:45:21      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:you   called   结构   rgb   cal   最小堆   推出   中位数   public   

问题:

设计结构体,能够满足以下两个功能:

  • 向结构体中插入数据  void addNum(int num)
  • 去当前结构体中的中位数  double findMedian()
    • 若共有奇数个数,取最中间的数
    • 若共有偶数个数,取中间两个数之和/2
Example 1:

Input
["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"]
[[], [1], [2], [], [3], []]
Output
[null, null, null, 1.5, null, 2.0]

Explanation
MedianFinder medianFinder = new MedianFinder();
medianFinder.addNum(1);    // arr = [1]
medianFinder.addNum(2);    // arr = [1, 2]
medianFinder.findMedian(); // return 1.5 (i.e., (1 + 2) / 2)
medianFinder.addNum(3);    // arr[1, 2, 3]
medianFinder.findMedian(); // return 2.0
 

Constraints:

-10^5 <= num <= 10^5
There will be at least one element in the data structure before calling findMedian.
At most 5 * 10^4 calls will be made to addNum and findMedian.
 

Follow up:

If all integer numbers from the stream are in the range [0, 100], how would you optimize your solution?
If 99% of all integer numbers from the stream are in the range [0, 100], how would you optimize your solution?

  

解法:priority_queue, heap(优先队列,最大堆,最小堆)

思路:

要求中位数,即一堆数排序后,最中间的一个or两个数。

那么我们可以考虑,使用两个heap,

  • 一个记录最小的一半数。smaller
  • 一个记录最大的一半数。larger

那么中位数,只相关于:smaller中最大的,larger中最小的数。

因此 smaller使用最大堆,larger使用最小堆,

这样,top即为所求相关数。

 

我们考虑如何插入:

  • 要保证smaller和larger各保存一半数据。
  • ?? 数据个数==奇数时,larger方保存更多的一个。

那么,若当前有偶数个数:

新插入的数需要最终插入larger方,

因此我们先将其插入smaller方->smaller中会推出一个最大值,将这个最大值,再最终插入larger方。

若当前有奇数个数:(lager方一定多一个)

新插入的数需要最终插入smaller方,

因此我们先将其插入larger方->larger方会推出一个最小值,再将这个最小值,最终插入smaller方。

?? 注意:记得同时更新总个数的奇偶性,even=!even

 

那么所求中位数为:

  • 数据总个数==奇数:
    • larger方的top(由于?? )
  • 数据总个数==偶数:
    • (smaller方top+larger方top) / 2

 

代码参考:

 1 class MedianFinder {
 2 public:
 3     /** initialize your data structure here. */
 4     MedianFinder() {
 5         
 6     }
 7     
 8     void addNum(int num) {
 9         if(even) {
10             //first to insert to lager queue.
11             smaller.push(num);
12             larger.push(smaller.top());
13             smaller.pop();
14         } else {
15             larger.push(num);
16             smaller.push(larger.top());
17             larger.pop();
18         }
19         even = !even;
20     }
21     
22     double findMedian() {
23         if(even) {
24             return ( smaller.top()+larger.top() ) / 2.0;
25         } else {
26             return larger.top();
27         }
28     }
29 private:
30     priority_queue<int, vector<int>, greater<int>> larger;//top->smallest element
31     priority_queue<int> smaller;//top->largest element
32     bool even=true;
33 };
34 
35 /**
36  * Your MedianFinder object will be instantiated and called as such:
37  * MedianFinder* obj = new MedianFinder();
38  * obj->addNum(num);
39  * double param_2 = obj->findMedian();
40  */

 

295. Find Median from Data Stream

标签:you   called   结构   rgb   cal   最小堆   推出   中位数   public   

原文地址:https://www.cnblogs.com/habibah-chang/p/14662488.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!