Median of Data Stream Using Two Heaps in DSA Javascript - Time & Space Complexity
We want to know how fast we can find the middle value when numbers keep coming in.
How does the time to add numbers and get the middle change as more numbers arrive?
Analyze the time complexity of the following code snippet.
class MedianFinder {
constructor() {
this.small = new MaxHeap(); // lower half
this.large = new MinHeap(); // upper half
}
addNum(num) {
this.small.insert(num);
this.large.insert(this.small.extractMax());
if (this.large.size() > this.small.size()) {
this.small.insert(this.large.extractMin());
}
}
findMedian() {
if (this.small.size() > this.large.size()) return this.small.peek();
return (this.small.peek() + this.large.peek()) / 2;
}
}
This code keeps two heaps to quickly find the median as numbers are added.
Look at what repeats when adding numbers.
- Primary operation: Inserting and extracting from heaps (insert, extractMax, extractMin).
- How many times: Each addNum call does a few heap operations, each on a smaller set of numbers.
Each new number causes a few heap operations that take longer as the heaps grow.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 insertions and extractions, each quick. |
| 100 | About 100 insertions and extractions, each a bit slower. |
| 1000 | About 1000 insertions and extractions, each slower but still efficient. |
Pattern observation: The time per add grows slowly, roughly like the height of the heaps, which grows with the log of input size.
Time Complexity: O(log n)
This means adding each number and updating the median takes time that grows slowly as more numbers come in.
[X] Wrong: "Adding a number takes constant time because we just put it somewhere."
[OK] Correct: Actually, we must keep the heaps balanced and ordered, so inserting and extracting take time that grows with the heap size.
Understanding this method shows you can handle data that changes over time and still find answers quickly.
"What if we used only one heap instead of two? How would the time complexity change?"
Practice
Solution
Step 1: Understand the role of two heaps
The max-heap stores the smaller half of the numbers, and the min-heap stores the larger half.Step 2: Explain how this helps find the median
By balancing these heaps, the median is either the top of one heap or the average of the tops of both heaps.Final Answer:
To efficiently keep track of the lower half and upper half of the numbers separately -> Option BQuick Check:
Two heaps split data halves = A [OK]
- Thinking heaps sort all numbers fully
- Using only one heap for median
- Confusing max-heap and min-heap roles
Solution
Step 1: Decide heap based on number value
If the number is smaller or equal to the max-heap root, it belongs to the lower half, so insert into max-heap.Step 2: Otherwise insert into min-heap
If the number is greater, it belongs to the upper half, so insert into min-heap.Final Answer:
Insert into max-heap if number is less than or equal to max-heap root; else insert into min-heap -> Option CQuick Check:
Compare with max-heap root to choose heap [OK]
- Inserting all numbers into one heap
- Not comparing with max-heap root
- Inserting randomly without condition
const maxHeap = new MaxHeap();
const minHeap = new MinHeap();
function addNum(num) {
if (maxHeap.size() === 0 || num <= maxHeap.peek()) {
maxHeap.insert(num);
} else {
minHeap.insert(num);
}
if (maxHeap.size() > minHeap.size() + 1) {
minHeap.insert(maxHeap.extract());
} else if (minHeap.size() > maxHeap.size()) {
maxHeap.insert(minHeap.extract());
}
}
addNum(5);
addNum(15);
addNum(1);
addNum(3);
const median = maxHeap.size() > minHeap.size() ? maxHeap.peek() : (maxHeap.peek() + minHeap.peek()) / 2;
console.log(median);
What is the output printed?Solution
Step 1: Insert numbers and balance heaps
Insert 5 into maxHeap (empty). Insert 15 into minHeap (15 > 5). Insert 1 into maxHeap (1 <= 5). Insert 3 into maxHeap (3 <= 5). Now maxHeap has 3 elements, minHeap has 1.Step 2: Balance heaps sizes
maxHeap size (3) > minHeap size (1) + 1, so move maxHeap.extract() (which is 5) to minHeap. Now maxHeap has [3,1], minHeap has [5,15]. Median is average of maxHeap.peek()=3 and minHeap.peek()=5, so (3+5)/2 = 4.Final Answer:
4 -> Option AQuick Check:
Median after balancing = 4 [OK]
- Not balancing heaps after insertion
- Taking median as maxHeap.peek() only
- Incorrect heap extraction order
function addNum(num) {
if (num < maxHeap.peek()) {
maxHeap.insert(num);
} else {
minHeap.insert(num);
}
if (maxHeap.size() > minHeap.size() + 1) {
minHeap.insert(maxHeap.extract());
} else if (minHeap.size() > maxHeap.size()) {
maxHeap.insert(minHeap.extract());
}
}
What is the bug in this code?Solution
Step 1: Identify peek() usage problem
The code calls maxHeap.peek() without checking if maxHeap is empty, causing an error on first insertion.Step 2: Explain impact of missing empty check
Without checking, calling peek() on empty maxHeap throws an error, so the first number cannot be inserted properly.Final Answer:
It does not handle the case when maxHeap is empty before peek() -> Option DQuick Check:
Empty maxHeap peek() causes error [OK]
- Ignoring empty heap before peek()
- Assuming heaps always balanced before insert
- Incorrect size comparison operators
Solution
Step 1: Insert numbers and balance heaps
Insert 2 (maxHeap empty, goes to maxHeap). Insert 4 (4 > 2, minHeap). Insert 7 (7 > 2, minHeap). Now minHeap has 2 elements, maxHeap 1, so move minHeap.extract() (4) to maxHeap. Insert 1 (1 <= 4, maxHeap). Insert 5 (5 > 4, minHeap). Insert 3 (3 <= 4, maxHeap). Heaps are balanced with maxHeap size 4 and minHeap size 2, move maxHeap.extract() (4) to minHeap to balance sizes.Step 2: Calculate median and explain balancing
Now maxHeap has [3,2,1] with peek()=3, minHeap has [4,5,7] with peek()=4. Since sizes equal (3 and 3), median is (3 + 4)/2 = 3.5. Balancing keeps heaps sizes equal or off by one to find median correctly from the tops.Final Answer:
3.5; Balancing keeps heaps sizes equal or off by one to find median correctly -> Option AQuick Check:
Balanced heaps give median 3.5 [OK]
- Not balancing heaps after each insertion
- Calculating median from unsorted data
- Confusing median with max or min values
Ready to prove it?
Pass the test and this pattern moves unknown
