Heap Extract Min or Max Bubble Down in DSA C++ - 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.
// Extract min from a min-heap and bubble down to fix heap
int extractMin(std::vector<int>& heap) {
int minVal = heap[0];
heap[0] = heap.back();
heap.pop_back();
int i = 0;
int n = heap.size();
while (true) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int smallest = i;
if (left < n && heap[left] < heap[smallest]) smallest = left;
if (right < n && heap[right] < heap[smallest]) smallest = right;
if (smallest == i) break;
std::swap(heap[i], heap[smallest]);
i = smallest;
}
return minVal;
}
This code removes the smallest item from a min-heap and then moves the new root down to restore the heap order.
- Primary operation: The while loop that moves the root element down the heap to fix order.
- How many times: At most, this loop runs once per level of the heap, from root to leaf.
Each time we bubble down, we move one level down the heap tree. The heap height grows slowly as the heap size grows.
| Input Size (n) | Approx. Operations (levels to bubble down) |
|---|---|
| 10 | About 3 to 4 steps |
| 100 | About 6 to 7 steps |
| 1000 | About 9 to 10 steps |
Pattern observation: The number of steps grows slowly, roughly proportional to the height of the heap, which is about log base 2 of n.
Time Complexity: O(log n)
This means the time to extract and fix the heap grows slowly, increasing only a little even if the heap gets much bigger.
[X] Wrong: "Extracting min takes constant time because we just remove the root."
[OK] Correct: Removing the root is quick, but fixing the heap order by moving the new root down can take several steps depending on heap height.
Knowing this time complexity helps you explain why heaps are efficient for priority queues and sorting, showing you understand how data structure operations scale.
"What if the heap was a max-heap instead of a min-heap? How would the time complexity of extract and 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 is moved to the root position.Step 2: Apply bubble down to restore heap
The bubble down operation moves this element down the tree to restore the min-heap property by swapping with the smaller child.Final Answer:
To restore the min-heap property by moving the root element down to its correct position -> Option AQuick Check:
Bubble down fixes heap after extract-min [OK]
- Thinking bubble down inserts new elements
- Confusing bubble down with bubble up
- Assuming bubble down removes max element
heap[i] and heap[j] during bubble down?Solution
Step 1: Recall C++ swap function usage
The standard way to swap two variables in C++ is usingswap(a, b);from<algorithm>.Step 2: Check each option
swap(heap[i], heap[j]); uses correct syntax. heap[i] = heap[j]; heap[j] = heap[i]; wrongly assigns values without temporary storage. Options C and D have invalid syntax.Final Answer:
swap(heap[i], heap[j]); -> Option DQuick Check:
Correct swap syntax = swap(heap[i], heap[j]); [OK]
- Assigning without temporary variable causes errors
- Adding extra symbols after swap call
- Using braces {} after swap incorrectly
[2, 5, 3, 10, 7], after extracting the minimum element and performing bubble down, what is the resulting heap array?Solution
Step 1: Remove minimum and replace root
Remove 2 (root). Move last element 7 to root: [7, 5, 3, 10]Step 2: Bubble down 7 to restore min-heap
Compare 7 with children 5 and 3. Smallest child is 3. Swap 7 and 3: [3, 5, 7, 10]. Now 7 has children 10 only, no swap needed.Final Answer:
[3, 5, 7, 10] -> Option AQuick Check:
Bubble down swaps root with smallest child [OK]
- Not swapping with smallest child first
- Forgetting to replace root with last element
- Swapping with larger child by mistake
void bubbleDown(vector<int>& heap, int i) {
int left = 2*i + 1;
int right = 2*i + 2;
int largest = i;
if (left < heap.size() && heap[left] > heap[largest])
largest = left;
if (right < heap.size() && heap[right] > heap[largest])
largest = right;
if (largest != i) {
swap(heap[i], heap[largest]);
bubbleDown(heap, largest);
}
}
What is the bug if the heap size is 1 and bubbleDown(heap, 0) is called?Solution
Step 1: Check conditions for size 1 heap
For size 1, left = 1 and right = 2, both >= heap.size(), so conditions fail and largest stays i.Step 2: Confirm no recursion or swap
Since largest == i, no swap or recursive call happens. Function returns safely.Final Answer:
No bug; function handles size 1 correctly -> Option BQuick Check:
Bounds checked before access prevents errors [OK]
- Assuming out-of-range access without checking
- Thinking recursion always happens
- Swapping when largest equals current index
[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 and replace root
Remove 50 (root). Move last element 35 to root: [35, 30, 40, 10, 20]Step 2: Bubble down 35 to restore max-heap
Compare 35 with children 30 and 40. Largest child is 40. Swap 35 and 40: [40, 30, 35, 10, 20]. Now 35 has children 10 and 20, both smaller, so stop.Final Answer:
[40, 30, 35, 10, 20] -> Option CQuick Check:
Bubble down swaps with largest child in max-heap [OK]
- Swapping with smaller child instead of largest
- Not replacing root with last element before bubble down
- Stopping bubble down too early
Ready to prove it?
Pass the test and this pattern moves unknown
