Algorithms first
数据流的中位数 · 交互式算法学习
支持数据流插入与 O(1) 查询中位数。
#295 · 堆
数据流的中位数
Find Median from Data Stream
addNum(1), addNum(2), findMedian(), addNum(3)栈 / 队列 / 堆3 个关键状态
步骤 11 进入较小半区。
lo=[1]推荐
最大堆 + 最小堆
时间
插入 O(log n)空间 O(n)小的一半放最大堆,大的一半放最小堆,大小差不超过 1。
1class Heap {2 constructor(compare) {3 this.a = [];4 this.compare = compare5 }6 push(x) {7 const a = this.a;8 a.push(x);9 let i = a.length - 1;10 while (i) {11 const p = (i - 1) >> 1;12 if (!this.compare(a[i], a[p])) break;13 [a[i], a[p]] = [a[p], a[i]];14 i = p15 }16 }17 pop() {18 const a = this.a;19 if (!a.length) return undefined;20 const top = a[0],21 last = a.pop();22 if (a.length) {23 a[0] = last;24 for (let i = 0;;) {25 let best = i,26 l = i * 2 + 1,27 r = l + 1;28 if (l < a.length && this.compare(a[l], a[best])) best = l;29 if (r < a.length && this.compare(a[r], a[best])) best = r;30 if (best === i) break;31 [a[i], a[best]] = [a[best], a[i]];32 i = best33 }34 }35 return top36 }37 peek() {38 return this.a[0]39 }40 get size() {41 return this.a.length42 }43}44class MedianFinder {45 constructor() {46 this.lo = new Heap((a, b) => a > b);47 this.hi = new Heap((a, b) => a < b)48 }49 addNum(x) {50 this.lo.push(x);51 this.hi.push(this.lo.pop());52 if (this.hi.size > this.lo.size) this.lo.push(this.hi.pop())53 }54 findMedian() {55 return this.lo.size > this.hi.size ? this.lo.peek() : (this.lo.peek() + this.hi.peek()) / 256 }57}多语言参考
来源 · CC BY-SA 4.0 ↗Java · C++ · Go
这是一组同题正确实现,独立于上方当前动画方法;不同语言可能采用另一种正确策略。
1class MedianFinder {2 private PriorityQueue<Integer> minQ = new PriorityQueue<>();3 private PriorityQueue<Integer> maxQ = new PriorityQueue<>(Collections.reverseOrder());4 5 public MedianFinder() {6 }7 8 public void addNum(int num) {9 maxQ.offer(num);10 minQ.offer(maxQ.poll());11 if (minQ.size() - maxQ.size() > 1) {12 maxQ.offer(minQ.poll());13 }14 }15 16 public double findMedian() {17 return minQ.size() == maxQ.size() ? (minQ.peek() + maxQ.peek()) / 2.0 : minQ.peek();18 }19}20 21/**22 * Your MedianFinder object will be instantiated and called as such:23 * MedianFinder obj = new MedianFinder();24 * obj.addNum(num);25 * double param_2 = obj.findMedian();26 */交互式算法学习
从执行步骤真正理解 LeetCode 经典 150
本站整理 150 道高频算法面试题和 302 种解法。动画方法同步展示 JavaScript 与 Python;每题另提供 Java、C++ 与 Go 同题参考实现。
AlgoViz Lab
数据流的中位数 · 解法对比
支持数据流插入与 O(1) 查询中位数。
- 测试用例
addNum(1), addNum(2), findMedian(), addNum(3)- 题目分类
- 堆
- 解法对比
- 2
维护有序数组
二分找到插入位置后数组移动元素,中位数直接读取。
- 时间
插入 O(n)- 空间
O(n)
最大堆 + 最小堆
小的一半放最大堆,大的一半放最小堆,大小差不超过 1。
- 时间
插入 O(log n)- 空间
O(n)