一日一练:连续中值

135 阅读1分钟

随机产生数字并传递给一个方法。你能否完成这个方法,在每次产生新值时,寻找当前所有值的中间值(中位数)并保存。中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。

这里需要实现三个方法,

  • 构造函数 MedianFinder
  • 实例方法 addNum
  • 实例方法 findMedian

主要实现的是addNum方法,如何在加入新num之后维护新的队列。

排序

最简单的想法是,每次加入新数据之后 都给队列排序

var MedianFinder = function() {
    this.data = []
};


MedianFinder.prototype.addNum = function(num) {
    this.data.push(num)
    this.data.sort((a, b) => (a - b))
};

MedianFinder.prototype.findMedian = function() {
  const len = this.data.length
  if (len % 2 === 0) {
      return (this.data[len / 2] + this.data[len / 2 - 1]) / 2
  } else {
      return this.data[len >> 1]
  }
};

排序 + 二分

这里可以在addNum之后用二分每次确定新num的位置,然后放到对应的位置

MedianFinder.prototype.addNum = function(num) {
  if (this.data.length === 0) {
      return this.data.push(num)
  }
  let pos = this.findIdx(num)
  if (pos <= 0) {
      this.data.unshift(num)
  } else if (pos >= this.data.length) {
      this.data.push(num)
  } else {
      this.data.splice(pos, 0, num)
  }
};

// 二分查找新数据的位置
MedianFinder.prototype.findIdx = function(num) {
  let left = -1, right = this.data.length
  while(left < right) {
      let mid = left + ((right - left) >> 1)
      if (this.data[mid] <= num) {
          left = mid + 1
      } else {
          right = mid
      }
  }
  return left
}