Heap Extract Min or Max Bubble Down in DSA Go - Time & Space Complexity
We analyze how long it takes to remove the top element from a heap and restore order.
How does the work grow as the heap size increases?
Analyze the time complexity of the following code snippet.
func bubbleDown(heap []int, index int) {
n := len(heap)
smallest := index
left := 2*index + 1
right := 2*index + 2
if left < n && heap[left] < heap[smallest] {
smallest = left
}
if right < n && heap[right] < heap[smallest] {
smallest = right
}
if smallest != index {
heap[index], heap[smallest] = heap[smallest], heap[index]
bubbleDown(heap, smallest)
}
}
This code restores the heap property by moving the root element down to its correct position.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Recursive calls moving down the heap levels.
- How many times: Up to the height of the heap, which is about log n.
Each recursive step compares and swaps with children, moving down one level.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 3 to 4 steps |
| 100 | About 6 to 7 steps |
| 1000 | About 9 to 10 steps |
Pattern observation: Operations grow slowly, roughly proportional to the height of the heap, which increases logarithmically.
Time Complexity: O(log n)
This means the time to fix the heap grows slowly as the heap gets bigger, only about the height of the tree.
[X] Wrong: "Bubble down takes linear time because it looks at many elements."
[OK] Correct: It only moves down one path from root to leaf, not all elements, so it takes time proportional to the tree height, not the total number of elements.
Understanding this helps you explain how heaps keep their order efficiently after removals, a key skill for many coding problems.
"What if the heap was a ternary heap (each node has 3 children) instead of binary? How would the time complexity 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.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 BQuick Check:
Bubble down fixes heap after extract-min [OK]
- Thinking bubble down adds elements
- Confusing bubble down with bubble up
- Believing bubble down swaps min and max
i in slice heap?Solution
Step 1: Identify bubble down for min-heap
Bubble down compares current node with children and swaps with smallest child.Step 2: Check code correctness
for { left := 2*i + 1 right := 2*i + 2 smallest := i if left < len(heap) && heap[left] < heap[smallest] { smallest = left } if right < len(heap) && heap[right] < heap[smallest] { smallest = right } if smallest == i { break } heap[i], heap[smallest] = heap[smallest], heap[i] i = smallest } correctly finds smallest child and swaps until heap property is restored.Final Answer:
Option A code snippet correctly implements bubble down for min-heap -> Option AQuick Check:
Min-heap bubble down uses smallest child swap [OK]
- Using 1-based indexing instead of 0-based
- Swapping with largest child in min-heap
- Using bubble up logic instead of bubble down
heap := []int{2, 4, 5, 10, 8, 15}, what will be the heap slice after extracting the minimum element and performing bubble down?Solution
Step 1: Remove min and replace root
Remove 2 (root), move last element 15 to root: [15,4,5,10,8]Step 2: Bubble down 15
Compare 15 with children 4 and 5; swap with 4 (smallest). Now heap: [4,15,5,10,8]. Next, bubble down 15 at index 1: children 10 and 8; swap with 8 (smallest). Final heap: [4,8,5,10,15]Final Answer:
[4, 8, 5, 10, 15] -> Option AQuick Check:
Extract min + bubble down = [4,8,5,10,15] [OK]
- Not swapping with smallest child first
- Forgetting to move last element to root
- Swapping with larger child
func bubbleDown(heap []int, i int) {
for {
left := 2*i + 1
right := 2*i + 2
largest := i
if left < len(heap) && heap[left] < heap[largest] {
largest = left
}
if right < len(heap) && heap[right] < heap[largest] {
largest = right
}
if largest == i {
break
}
heap[i], heap[largest] = heap[largest], heap[i]
i = largest
}
}Solution
Step 1: Understand max-heap bubble down logic
In max-heap, bubble down swaps with the largest child, so comparisons should find the largest value.Step 2: Identify incorrect comparison operators
The code uses '<' to find smaller child, which is wrong for max-heap; it should use '>' to find largest child.Final Answer:
The comparisons use '<' instead of '>' for max-heap -> Option DQuick Check:
Max-heap bubble down uses '>' comparisons [OK]
- Using wrong comparison operators for heap type
- Incorrect child index calculations
- Misplacing swap inside or outside loop
heap := []int{50, 30, 40, 10, 20, 35}. After extracting the maximum element and performing bubble down, what will be the resulting heap slice?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
Compare 35 with children 30 and 40; swap with 40 (largest). Now heap: [40,30,35,10,20]. Next, bubble down 35 at index 2: children indices 5 and 6 do not exist (len=5), so stop. This restores the max-heap property.Final Answer:
[40, 30, 35, 10, 20] -> Option CQuick Check:
Extract max + bubble down = [40,30,35,10,20] [OK]
- Not swapping with largest child first
- Stopping bubble down too early
- Ignoring heap property for children
Ready to prove it?
Pass the test and this pattern moves unknown
