Heap Extract Min or Max Bubble Down in DSA Typescript - Time & Space Complexity
We want to understand how long it takes to remove the smallest or largest item from a heap and fix the heap order.
How does the time needed grow as the heap gets bigger?
Analyze the time complexity of the following code snippet.
function bubbleDown(heap: number[], index: number = 0): void {
const length = heap.length;
let smallest = index;
const left = 2 * index + 1;
const right = 2 * index + 2;
if (left < length && heap[left] < heap[smallest]) smallest = left;
if (right < length && heap[right] < heap[smallest]) smallest = right;
if (smallest !== index) {
[heap[index], heap[smallest]] = [heap[smallest], heap[index]];
bubbleDown(heap, smallest);
}
}
This code removes the top element from a min-heap and moves the last element down to restore heap order by swapping with smaller children.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls to bubbleDown that compare and swap elements.
- How many times: At most once per level of the heap, moving down from root to leaf.
Each recursive call moves down one level in the heap tree, which grows slowly as the heap size grows.
| Input Size (n) | Approx. Operations (levels) |
|---|---|
| 10 | About 4 steps |
| 100 | About 7 steps |
| 1000 | About 10 steps |
Pattern observation: The number of steps grows slowly, roughly with the height of the heap, which is much smaller than the total number of elements.
Time Complexity: O(log n)
This means the time to fix the heap grows slowly, proportional to the height of the heap tree.
[X] Wrong: "Bubble down takes linear time because it might check every element in the heap."
[OK] Correct: The bubble down only moves down one path from root to leaf, not all elements, so it only takes time proportional to the tree height, not the total number of elements.
Understanding this helps you explain how heaps efficiently keep order when removing items, a key skill for many coding challenges.
What if we changed the heap to a max-heap? How would the time complexity of bubble down change?
Practice
bubble down operation in a min-heap after extracting the minimum element?Solution
Step 1: Understand extract-min operation
When the minimum element (root) is removed, the last element replaces the root.Step 2: Apply bubble down to restore heap
The bubble down moves this element down the tree to restore the min-heap property.Final Answer:
To restore the heap property by moving the root element down to its correct position -> Option DQuick Check:
Bubble down fixes heap after extract-min [OK]
- Confusing bubble down with insertion
- Thinking bubble down swaps min and max
- Assuming bubble down deletes elements
Solution
Step 1: Check valid swap syntax in TypeScript
const temp = heap[i]; heap[i] = heap[j]; heap[j] = temp; uses a temporary variable to swap two elements correctly.Step 2: Identify incorrect syntax in other options
heap[i], heap[j] = heap[j], heap[i]; uses Python-style unpacking (invalid in TypeScript), C calls undefined function, D overwrites values incorrectly.Final Answer:
const temp = heap[i]; heap[i] = heap[j]; heap[j] = temp; -> Option BQuick Check:
Use temp variable to swap in TypeScript [OK]
- Using Python tuple swap syntax in TypeScript
- Calling undefined swap function
- Overwriting values without temp variable
[2, 5, 3, 10, 7]. After extracting the minimum element and performing bubble down, what is the resulting heap array?Solution
Step 1: Remove root and replace with last element
Remove 2, replace root with 7: [7, 5, 3, 10]Step 2: Bubble down 7 to restore min-heap
Compare 7 with children 5 and 3; swap with smallest child 3: [3, 5, 7, 10]Final Answer:
[3, 5, 7, 10] -> Option AQuick Check:
Extract min and bubble down result = [3, 5, 7, 10] [OK]
- Not replacing root with last element
- Swapping with wrong child during bubble down
- Forgetting to remove last element
function bubbleDown(heap: number[], i: number) {
const left = 2 * i + 1;
const right = 2 * i + 2;
let largest = i;
if (left < heap.length && heap[left] > heap[largest]) {
largest = left;
}
if (right < heap.length && heap[right] > heap[largest]) {
largest = right;
}
if (largest !== i) {
heap[i] = heap[largest];
heap[largest] = heap[i];
bubbleDown(heap, largest);
}
}Solution
Step 1: Analyze swap logic in code
The swap uses heap[i] = heap[largest]; heap[largest] = heap[i]; which overwrites heap[i] before assigning heap[largest].Step 2: Identify correct swap method
Swapping requires a temporary variable to avoid overwriting values.Final Answer:
Swapping elements overwrites values incorrectly without a temporary variable -> Option AQuick Check:
Swap needs temp variable to avoid overwrite [OK]
- Overwriting values during swap without temp
- Confusing bubbleDown with bubbleUp
- Incorrect child index calculations
[50, 30, 40, 10, 20, 35]. After extracting the maximum element and performing bubble down, what is the final heap array?Solution
Step 1: Remove max (root) and replace with last element
Remove 50, replace root with 35: [35, 30, 40, 10, 20]Step 2: Bubble down 35 to restore max-heap
Compare 35 with children 30 and 40; swap with largest child 40: [40, 30, 35, 10, 20]Final Answer:
[40, 30, 35, 10, 20] -> Option CQuick Check:
Extract max and bubble down result = [40, 30, 35, 10, 20] [OK]
- Swapping with wrong child during bubble down
- Not removing last element after replacement
- Confusing min-heap bubble down with max-heap
Ready to prove it?
Pass the test and this pattern moves unknown
