随机产生数字并传递给一个方法。你能否完成这个方法,在每次产生新值时,寻找当前所有值的中间值(中位数)并保存。
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[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
分析
- 实现一个最大堆从小到大排序,实现一个最小堆从大到小排序
- 维护最大堆、最小堆,始终保持最大堆比最小堆多1个或相等,当最大堆、最小堆的长度相等取(最大堆的最后一个+最小堆最后一个)/2,当最大堆的长度大于取最大堆的最后一个
代码实现
/**
* initialize your data structure here.
*/
var MedianFinder = function() {
this.left = [-Infinity]
this.right = [Infinity]
};
/**
* @param {number} num
* @return {void}
*/
MedianFinder.prototype.addNum = function(num) {
if(num <= this.left[this.left.length - 1]){
this.left.push(num)
this.left = this.left.sort((a,b) => a - b)
}else{
this.right.push(num)
this.right = this.right.sort((a,b) => b - a)
}
this.resize()
};
MedianFinder.prototype.resize = function(){
if(this.left.length - this.right.length >1){
this.right.push(this.left.pop())
}else if(this.right.length > this.left.length){
this.left.push(this.right.pop())
}
}
/**
* @return {number}
*/
MedianFinder.prototype.findMedian = function() {
if(this.left.length === this.right.length){
return (this.left[this.left.length-1] + this.right[this.right.length-1]) / 2
}else{
return this.left[this.left.length-1]
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* var obj = new MedianFinder()
* obj.addNum(num)
* var param_2 = obj.findMedian()
*/