0
点赞
收藏
分享

微信扫一扫

剑指 Offer 41. 数据流中的中位数

剑指 Offer 41. 数据流中的中位数_堆( 优先队列 )

思路

方法一:简单排序

将数字存储在可调整大小的容器中。每次需要输出中间值时,对容器进行排序并输出中间值。

复杂度分析

时间复杂度:剑指 Offer 41. 数据流中的中位数_复杂度分析_02

添加一个数字对于一个有效调整大小方案的容器来说需要花费 O(1) 的时间。
找到中间值主要取决于发生的排序。对于标准比较排序,这需要 O(nlogn) 时间。

空间复杂度:O(n) 线性空间,用于在容器中保存输入。除了需要的空间之外没有其他空间(因为通常可以在适当的位置进行排序)。

 

方法二:插入排序

保持输入容器始终排序。

复杂度分析

时间复杂度:O(n)+O(logn)≈O(n).

二分搜索需要花费 O(logn) 时间才能找到正确的插入位置。
插入可能需要花费 O(n) 的时间,因为必须在容器中移动元素为新元素腾出空间。

空间复杂度:O(n) 线性空间,用于在容器中保存输入。

 

方法三:一个大顶堆 + 一个小顶堆

一个大顶堆maxHeap, 一个小顶堆minHeap,大顶堆保存前一半的元素,小顶堆保存后一半的元素。

与此同时,始终保持两个堆的大小之差不超过1。

为了保证这两个堆大小之差不超过1,对于元素num的插入过程需分为以下3种情况:

(1) 大顶堆的元素个数 = 小顶堆的元素个数

  两个堆大小相等,如果小顶堆为空或者待插入的元素num≥小顶堆的堆顶元素,则直接把num插入小顶堆中;

  否则,把num插入大顶堆中。

(2) 大顶堆的元素个数 < 小顶堆的元素个数

  如果待插入的元素num≤小顶堆的堆顶元素,则直接把num插入大顶堆中;

  否则,弹出小顶堆的堆顶元素,并将其插入大顶堆,之后把num插入小顶堆。

(3) 大顶堆的元素个数 > 小顶堆的元素个数

  如果待插入的元素num≥大顶堆的堆顶元素,则直接把num插入小顶堆中;

  否则,弹出大顶堆的堆顶元素,并将其插入小顶堆,之后把num插入大顶堆。

复杂度分析

时间复杂度:O(logn)。堆的插入删除操作都是O(logn)。

空间复杂度:O(n) 。小顶堆剑指 Offer 41. 数据流中的中位数_时间复杂度_03

1 class MedianFinder {
2 private:
3 priority_queue<int, vector<int>, greater<int>> minHeap;
4 priority_queue<int, vector<int>, less<int>> maxHeap;
5 public:
6 /** initialize your data structure here. */
7 MedianFinder() {
8
9 }
10
11 /*始终保持两个堆的大小之差不超过1*/
12 void addNum(int num) {
13 if(maxHeap.size() == minHeap.size()) {
14 /*如果两个堆大小相等*/
15 if(minHeap.empty()) {
16 minHeap.push(num);
17 return;
18 }
19
20 if(num >= minHeap.top()) {
21 minHeap.push(num);
22 } else {
23 maxHeap.push(num);
24 }
25
26 } else if(maxHeap.size() < minHeap.size()) {
27 /*如果大顶堆的元素少于小顶堆*/
28 if(num <= minHeap.top()) {
29 maxHeap.push(num);
30 } else {
31 maxHeap.push(minHeap.top());
32 minHeap.pop();
33 minHeap.push(num);
34 }
35
36 } else {
37 /*如果大顶堆的元素多于小顶堆*/
38 if(num >= maxHeap.top()) {
39 minHeap.push(num);
40 } else {
41 minHeap.push(maxHeap.top());
42 maxHeap.pop();
43 maxHeap.push(num);
44 }
45 }
46 }
47
48 double findMedian() {
49 if(maxHeap.size() == minHeap.size()) {
50 return (maxHeap.top() + minHeap.top()) / 2.0;
51 } else if(maxHeap.size() < minHeap.size()) {
52 return minHeap.top();
53 } else {
54 return maxHeap.top();
55 }
56 }
57 };
58
59 /**
60 * Your MedianFinder object will be instantiated and called as such:
61 * MedianFinder* obj = new MedianFinder();
62 * obj->addNum(num);
63 * double param_2 = obj->findMedian();
64 */

 

参考

​​力扣官方题解 - 数据流的中位数​​

 


举报

相关推荐

0 条评论