题目
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。 double findMedian() - 返回目前所有元素的中位数。 示例:
addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2
来源:力扣(LeetCode)leetcode-cn.com/problems/fi…
解题思路
- 把列表中的数字分两个区域,用一个大顶堆存小数,一个小顶堆存大数
- 两个堆都为空时添加到小数区,要添加的数小于等于小数区的最大元素时加入小数区,否则加入大数区
- 保持两个区的数字差不大于1
- 如果小数区数字总数大于大数区 2 个时,小数区出队列一个元素入队列到大数区
- 如果大数区数字总数大于小数区时,大数区出队列一个元素入队列到小数区
- 计算中位数
- 两个区域数字总数相等时,取两个队列的顶部元素相加再除 2
- 小数区数字多时中位数就是小数区的顶部元素
代码实现
var MedianFinder = function() {
this.minQueue = new MaxPriorityQueue() //3,2,1
this.maxQueue = new MinPriorityQueue() //4,5
};
/**
* @param {number} num
* @return {void}
*/
MedianFinder.prototype.addNum = function(num) {
if (this.minQueue.isEmpty() || num <= this.minQueue.front()['priority']) {
this.minQueue.enqueue(num)
if (this.minQueue.size() - this.maxQueue.size() > 1) {
this.maxQueue.enqueue(this.minQueue.dequeue()['priority'])
}
} else {
this.maxQueue.enqueue(num)
if (this.maxQueue.size() > this.minQueue.size()) {
this.minQueue.enqueue(this.maxQueue.dequeue()['priority'])
}
}
};
/**
* @return {number}
*/
MedianFinder.prototype.findMedian = function() {
if (this.minQueue.size() > this.maxQueue.size()) {
return this.minQueue.front()['priority']
}
return (this.minQueue.front()['priority'] + this.maxQueue.front()['priority']) / 2.0
};
如有错误欢迎指出,欢迎一起讨论!