[路飞]_程序员必刷力扣题: 面试题 17.20. 连续中值

144 阅读2分钟

面试题 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

二分插入

根据题意可知,我们需要不断往数据流中插入新的值

之后还要可以返回连续中值,即中位数

所以这是一个排序的问题,最后找出中位数即可,这里我们用二分查找的方式找到对应值来插入元素

  • 初始化类,我们需要一个data来保存所有的数据流
  • 如果为空,则直接push进去
  • 接下来声明起点start和终点end,循环来找到插入的位置,用splice来插入数组

这样我们就能一直得到一个有序数组data

接下来找到中位数

  • 偶数个,两个中位数的平均值,夏斌分别为(len - 1) >> 1和((len - 1) >> 1) + 1
  • 奇数个,中位数下标为(len - 1) >> 1

思路

/**
 * initialize your data structure here.
 */
var MedianFinder = function () {
    this.data = []
};

/** 
 * @param {number} num
 * @return {void}
 */
MedianFinder.prototype.addNum = function (num) {
    var data = this.data
    if (data.length === 0) {
        data.push(num)
        return
    }
    var start = 0;
    var end = data.length - 1;

    while (start <= end) {
        var mid = (start + end) >> 1
        if (data[mid] <= num) start = mid + 1
        if (data[mid] > num) end = mid - 1
    }
    data.splice(start, 0, num)
};

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

/**
 * Your MedianFinder object will be instantiated and called as such:
 * var obj = new MedianFinder()
 * obj.addNum(num)
 * var param_2 = obj.findMedian()
 */