|
| 1 | +/** |
| 2 | + * https://leetcode.com/problems/find-median-from-data-stream/ |
| 3 | + * Your MedianFinder object will be instantiated and called as such: |
| 4 | + * var obj = new MedianFinder() |
| 5 | + * obj.addNum(num) |
| 6 | + * var param_2 = obj.findMedian() |
| 7 | + */ |
| 8 | +class MedianFinder { |
| 9 | + constructor () { |
| 10 | + this.maxHeap = new MaxPriorityQueue() |
| 11 | + this.minHeap = new MinPriorityQueue() |
| 12 | + } |
| 13 | + |
| 14 | + /* Time O(log(N)) | Space (N) */ |
| 15 | + insertNum (num) { |
| 16 | + this.addNum(num) |
| 17 | + } |
| 18 | + |
| 19 | + addNum (num, heap = this.getHeap(num)) { |
| 20 | + heap.enqueue(num) |
| 21 | + this.rebalance() |
| 22 | + } |
| 23 | + |
| 24 | + getHeap (num, { maxHeap, minHeap } = this) { |
| 25 | + const isFirst = maxHeap.isEmpty() |
| 26 | + const isGreater = num <= this.top(maxHeap); |
| 27 | + const isMaxHeap = (isFirst || isGreater); |
| 28 | + return (isMaxHeap) |
| 29 | + ? maxHeap |
| 30 | + : minHeap |
| 31 | + } |
| 32 | + |
| 33 | + rebalance ({ maxHeap, minHeap } = this) { |
| 34 | + const canShiftMax = (minHeap.size() + 1) < maxHeap.size() |
| 35 | + if (canShiftMax) return minHeap.enqueue(maxHeap.dequeue().element) |
| 36 | + |
| 37 | + const canShiftMin = maxHeap.size() < minHeap.size() |
| 38 | + if (canShiftMin) return maxHeap.enqueue(minHeap.dequeue().element) |
| 39 | + } |
| 40 | + |
| 41 | + /* Time O(1) | Space (1) */ |
| 42 | + findMedian ({ maxHeap, minHeap } = this) { |
| 43 | + const isEven = maxHeap.size() === minHeap.size() |
| 44 | + return (isEven) |
| 45 | + ? this.average(maxHeap, minHeap) |
| 46 | + : this.top(maxHeap) |
| 47 | + } |
| 48 | + |
| 49 | + average (maxHeap, minHeap) { |
| 50 | + return (this.top(maxHeap) + this.top(minHeap)) / 2 |
| 51 | + } |
| 52 | + |
| 53 | + top (heap) { |
| 54 | + return heap.front()?.element || 0 |
| 55 | + } |
| 56 | +} |
0 commit comments