[路飞]_leetcode 面试题 17.20. 连续中值

301 阅读1分钟

题目来源:leetcode 面试题 17.20. 连续中值

随机产生数字并传递给一个方法。你能否完成这个方法,在每次产生新值时,寻找当前所有值的中间值(中位数)并保存。

中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

例如,

[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()
 */