题目链接
思路
利用数据结构的堆来解决这个问题 ------ 大根堆 小根堆
大根堆里面的内容 特征是 父节点的值 大于或者等于 其子节点的值
小根堆里面的内容 特征是 父节点的值 小于或者等于 其子节点的值
大根堆里面数据 其实就是 其中位数的 左边 的 ------ 比中位数小的内容
小根堆里面数据 其实就是 其中位数的 右边 的 ------ 比中位数大的内容
我们维护这俩个堆,大根堆可以比小根堆多一个,此时 数据是 奇数 中位数 是大根堆的堆顶,当大根堆和小根堆数据量一致时,代表此时数据是 偶数,返回 大根堆的堆顶 和 小根堆 的堆顶 俩个数字除以2 就是最后的内容
c++ java python 都有现成的数据结构可以使用,
js需要手写(参考了一个题解的写法)
代码:
javascript
var MedianFinder = function() {
function createHeap(type) { // type: 0-最小堆, 1-最大堆
const h = [null]; // 索引从1开始,方便计算
let size = 0;
function push(val) {
h[++size] = val;
up(size);
}
function up(u) {
// 当还有父节点且需要交换时
while (u >> 1 >= 1) {
const parent = u >> 1;
// 最小堆:子节点 < 父节点 时交换
// 最大堆:子节点 > 父节点 时交换
if ((type === 0 && h[u] < h[parent]) ||
(type === 1 && h[u] > h[parent])) {
[h[u], h[parent]] = [h[parent], h[u]];
u = parent;
} else {
break;
}
}
}
function down(u) {
while (u * 2 <= size) {
let t = u;
const left = u * 2;
const right = u * 2 + 1;
// 和左子节点比较
if ((type === 0 && h[t] > h[left]) ||
(type === 1 && h[t] < h[left])) {
t = left;
}
// 和右子节点比较
if (right <= size && (
(type === 0 && h[t] > h[right]) ||
(type === 1 && h[t] < h[right]))) {
t = right;
}
if (t !== u) {
[h[u], h[t]] = [h[t], h[u]];
u = t;
} else {
break;
}
}
}
function pop() {
if (size === 0) return null;
const top = h[1];
h[1] = h[size--];
down(1);
return top;
}
function peek() {
return h[1];
}
function getSize() {
return size;
}
function isEmpty() {
return size === 0;
}
return {
push,
pop,
peek,
getSize,
isEmpty
};
}
// 最大堆(存较小的一半)
this.maxHeap = createHeap(1);
// 最小堆(存较大的一半)
this.minHeap = createHeap(0);
};
MedianFinder.prototype.addNum = function(num) {
// 标准解法:先加入最大堆,然后把最大堆的最大值移到最小堆
if (this.maxHeap.isEmpty() || num <= this.maxHeap.peek()) {
this.maxHeap.push(num);
} else {
this.minHeap.push(num);
}
// 平衡两个堆的大小
// 最大堆可以比最小堆多一个元素,但不能少
if (this.maxHeap.getSize() > this.minHeap.getSize() + 1) {
this.minHeap.push(this.maxHeap.pop());
} else if (this.minHeap.getSize() > this.maxHeap.getSize()) {
this.maxHeap.push(this.minHeap.pop());
}
};
MedianFinder.prototype.findMedian = function() {
if (this.maxHeap.getSize() > this.minHeap.getSize()) {
// 奇数个元素,最大堆多一个
return this.maxHeap.peek();
} else {
// 偶数个元素,取平均值
return (this.maxHeap.peek() + this.minHeap.peek()) / 2;
}
};