面试题 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()
*/