Heap Sort Algorithm in DSA Go - Time & Space Complexity
We want to understand how the time taken by Heap Sort changes as the list size grows.
How does the number of steps increase when sorting bigger lists?
Analyze the time complexity of the following code snippet.
func heapSort(arr []int) {
n := len(arr)
for i := n/2 - 1; i >= 0; i-- {
heapify(arr, n, i)
}
for i := n - 1; i > 0; i-- {
arr[0], arr[i] = arr[i], arr[0]
heapify(arr, i, 0)
}
}
func heapify(arr []int, n, i int) {
largest := i
left := 2*i + 1
right := 2*i + 2
if left < n && arr[left] > arr[largest] {
largest = left
}
if right < n && arr[right] > arr[largest] {
largest = right
}
if largest != i {
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, largest)
}
}
This code builds a max heap from the array, then repeatedly swaps the largest element to the end and fixes the heap.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The
heapifyfunction called multiple times to maintain the heap property. - How many times: The first loop calls
heapifyabout n/2 times; the second loop callsheapifyn-1 times, each potentially recursing down the heap.
As the list size grows, the number of operations grows more than just a simple multiple.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 30 to 40 heapify steps |
| 100 | About 700 to 800 heapify steps |
| 1000 | About 10,000 heapify steps |
Pattern observation: The operations grow roughly proportional to n times log n, meaning it grows faster than n but slower than n squared.
Time Complexity: O(n log n)
This means if the list doubles in size, the time to sort grows a bit more than double, but much less than four times.
[X] Wrong: "Heap Sort is as slow as bubble sort because it uses loops inside loops."
[OK] Correct: Heap Sort uses a smart tree structure to reduce repeated work, so it sorts much faster than simple nested loops.
Understanding Heap Sort's time complexity shows you can analyze efficient sorting methods, a key skill in many coding challenges.
"What if we used a min heap instead of a max heap? How would the time complexity change?"
Practice
Solution
Step 1: Understand heap property
A heap is a special tree-based structure where the parent node is either greater (max-heap) or smaller (min-heap) than its children, allowing quick access to the largest or smallest element.Step 2: Role in Heap Sort
Heap Sort uses this property to repeatedly extract the largest element from the heap and place it at the end of the array, sorting the array efficiently.Final Answer:
To efficiently find and remove the largest (or smallest) element -> Option AQuick Check:
Heap = fast max/min extraction [OK]
- Thinking heap stores sorted elements permanently
- Confusing heap with a simple array
- Believing heap reverses array order
Solution
Step 1: Understand Go multiple assignment
Go allows swapping two variables in one line using multiple assignment syntax: arr[i], arr[j] = arr[j], arr[i].Step 2: Check other options
swap(arr[i], arr[j]) is invalid syntax in Go. arr[i] = arr[j]; arr[j] = arr[i] overwrites arr[i] before assigning arr[j]. temp = arr[i]; arr[j] = arr[i]; arr[i] = temp incorrectly sets arr[j] to old arr[i] and leaves arr[i] unchanged.Final Answer:
arr[i], arr[j] = arr[j], arr[i] -> Option BQuick Check:
Go swap uses multiple assignment [OK]
- Using invalid swap function call
- Overwriting one element before swapping
- Using incorrect temp assignment sequence
[4, 10, 3, 5, 1]?Solution
Step 1: Build max heap from array
Heapify the array to get max heap: [10, 5, 3, 4, 1]Step 2: Extract max and sort
Repeatedly swap max with last element and heapify remaining: final sorted array is [1, 3, 4, 5, 10]Final Answer:
[1, 3, 4, 5, 10] -> Option AQuick Check:
Heap Sort sorts ascending [OK]
- Confusing max heap with sorted array
- Forgetting to heapify after swaps
- Assuming heap sort outputs descending order
func heapify(arr []int, n, i int) {
largest := i
l := 2*i + 1
r := 2*i + 2
if l < n && arr[l] > arr[largest] {
largest = l
}
if r < n && arr[r] > arr[largest] {
largest = r
}
if largest != i {
arr[i], arr[largest] = arr[largest], arr[i]
heapify(arr, n, i)
}
}Solution
Step 1: Analyze recursive call
After swapping, heapify must continue from the new largest index to fix subtree, so call should be heapify(arr, n, largest).Step 2: Check other parts
Indices l and r are correct for binary heap. Swap syntax is valid Go. Function does not need to return value.Final Answer:
Recursive call should be heapify(arr, n, largest) instead of heapify(arr, n, i) -> Option CQuick Check:
Recursive call uses largest index [OK]
- Recursing on wrong index after swap
- Miscomputing child indices
- Thinking swap syntax is wrong in Go
Solution
Step 1: Understand stability and time complexity
Heap Sort is not stable because it swaps elements that may change relative order. It guarantees O(n log n) time always.Step 2: Compare with Quick Sort
Quick Sort is also not stable and can degrade to O(n²) in worst case, but often faster on average.Final Answer:
Heap Sort is not stable but has consistent O(n log n) time; Quick Sort is unstable and may degrade to O(n²) -> Option DQuick Check:
Heap Sort stable? No; Quick Sort worst-case O(n²) [OK]
- Assuming Heap Sort is stable
- Thinking Quick Sort is always faster
- Confusing stability with sorting speed
Ready to prove it?
Pass the test and this pattern moves unknown
