题目
- 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有值排序之后位于中间的数值。如果数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
- leetcode链接:https://leetcode-cn.com/problems/shu-ju-liu-zhong-de-zhong-wei-shu-lcof/
思路
- 维护一个大顶堆,一个小顶堆
- 插入奇数个的数,就先放到小顶堆,堆化之后再取出堆顶元素,插入到大顶堆中再堆化
- 插入偶数个的数,就先放到大顶堆,堆化之后再取出堆顶元素,插入到小顶堆中再堆化
- 大小顶堆个数相等时,分别拿堆顶元素再平分,如果个数不想等,从大顶堆拿堆顶元素
代码
/**
* initialize your data structure here.
*/
var MedianFinder = function () {
this.smallHeap = new SmallHeap()
this.bigHeap = new BigHeap()
}
/**
* @param {number} num
* @return {void}
*/
MedianFinder.prototype.addNum = function (num) {
if (this.smallHeap.size() === this.bigHeap.size()) {
this.smallHeap.insert(num)
const p = this.smallHeap.pick()
this.bigHeap.insert(p)
} else {
this.bigHeap.insert(num)
const p = this.bigHeap.pick()
this.smallHeap.insert(p)
}
}
/**
* @return {number}
*/
MedianFinder.prototype.findMedian = function () {
if (this.smallHeap.size() === this.bigHeap.size()) {
return (this.smallHeap.top() + this.bigHeap.top()) / 2
} else {
return this.bigHeap.top()
}
}
class SmallHeap {
constructor() {
this.heap = [null]
}
top() {
return this.heap[1]
}
size() {
return this.heap.slice(1).length
}
getHeap() {
return this.heap.slice(1)
}
insert(x) {
this.heap.push(x)
let index = this.heap.length - 1
while (
Math.floor(index / 2) > 0 &&
this.heap[Math.floor(index / 2)] > this.heap[index]
) {
swap(this.heap, Math.floor(index / 2), index)
index = Math.floor(index / 2)
}
}
pick() {
if (this.size()) {
swap(this.heap, 1, this.heap.length - 1)
const p = this.heap.pop()
this.heapify()
return p
}
}
heapify() {
let i = 1
while (i < this.heap.length) {
let minIndex = i
if (2 * i < this.heap.length && this.heap[2 * i] < this.heap[minIndex]) {
minIndex = 2 * i
}
if (
2 * i + 1 < this.heap.length &&
this.heap[2 * i + 1] < this.heap[minIndex]
) {
minIndex = 2 * i + 1
}
if (minIndex === i) break
swap(this.heap, minIndex, i)
i = minIndex
}
}
}
class BigHeap {
constructor() {
this.heap = [null]
}
top() {
return this.heap[1]
}
size() {
return this.heap.slice(1).length
}
getHeap() {
return this.heap.slice(1)
}
insert(x) {
this.heap.push(x)
let index = this.heap.length - 1
while (
Math.floor(index / 2) > 0 &&
this.heap[Math.floor(index / 2)] < this.heap[index]
) {
swap(this.heap, Math.floor(index / 2), index)
index = Math.floor(index / 2)
}
}
pick() {
if (this.size()) {
swap(this.heap, 1, this.heap.length - 1)
const p = this.heap.pop()
this.heapify()
return p
}
}
heapify() {
let i = 1
while (i < this.heap.length) {
let maxIndex = i
if (2 * i < this.heap.length && this.heap[2 * i] > this.heap[maxIndex]) {
maxIndex = 2 * i
}
if (
2 * i + 1 < this.heap.length &&
this.heap[2 * i + 1] > this.heap[maxIndex]
) {
maxIndex = 2 * i + 1
}
if (maxIndex === i) break
swap(this.heap, maxIndex, i)
i = maxIndex
}
}
}
function swap(arr, i, j) {
const temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}