Build Heap from Array Heapify in DSA C# - Time & Space Complexity
We want to understand how long it takes to build a heap from an array using heapify.
How does the time grow as the array gets bigger?
Analyze the time complexity of the following code snippet.
void BuildHeap(int[] arr) {
int n = arr.Length;
for (int i = n / 2 - 1; i >= 0; i--) {
Heapify(arr, n, i);
}
}
void Heapify(int[] arr, int n, int i) {
int largest = i;
int left = 2 * i + 1;
int 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) {
int temp = arr[i];
arr[i] = arr[largest];
arr[largest] = temp;
Heapify(arr, n, largest);
}
}
This code builds a max heap from an unsorted array by calling heapify on each non-leaf node.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The Heapify function called on each node from the bottom up.
- How many times: Heapify is called once for each non-leaf node, about n/2 times.
- Heapify itself may call itself recursively, moving down the tree.
Heapify work depends on the height of the node in the tree.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 to 30 operations |
| 100 | About 300 to 400 operations |
| 1000 | About 4000 to 5000 operations |
Pattern observation: The total work grows a bit faster than n but much slower than n squared because nodes near the bottom do less work.
Time Complexity: O(n)
This means building a heap from an array takes time proportional to the number of elements, not more.
[X] Wrong: "Heapify is called n/2 times and each call can take up to log n, so total time is O(n log n)."
[OK] Correct: Most Heapify calls happen on nodes near the bottom with small height, so they take less time. The total adds up to O(n), not O(n log n).
Knowing that building a heap is O(n) helps you explain why heap sort is efficient and shows you understand how recursion and loops combine in algorithms.
"What if we called Heapify starting from the root down to the leaves instead of bottom-up? How would the time complexity change?"
Practice
heapify process when building a heap from an array?Solution
Step 1: Understand heap property
A heap must satisfy the heap property where each parent node is greater (max-heap) or smaller (min-heap) than its children.Step 2: Role of heapify
The heapify process rearranges elements to ensure this property holds for every subtree starting from a node.Final Answer:
To rearrange the array elements to satisfy the heap property -> Option AQuick Check:
Heapify = Rearrange for heap property [OK]
- Thinking heapify sorts the array
- Confusing heapify with finding max/min element
- Assuming heapify reverses the array
Heapify method in C# for an array arr of size n at index i?Solution
Step 1: Check method signature
Heapify usually takes the array, its size, and the index to heapify as parameters in that order.Step 2: Match parameters order
Heapify(arr, n, i); matches the correct order: array, size, index.Final Answer:
Heapify(arr, n, i); -> Option AQuick Check:
Heapify(arr, n, i) correct call [OK]
- Mixing parameter order
- Passing index before array
- Confusing size and index positions
[4, 10, 3, 5, 1], what will be the array after calling Heapify(arr, 5, 1) assuming a max-heap?Solution
Step 1: Identify node at index 1
Value is 10, children at indices 3 (5) and 4 (1).Step 2: Check heap property
10 is greater than both children, so no swaps needed.Final Answer:
[4, 10, 3, 5, 1] -> Option CQuick Check:
Parent 10 > children 5,1 so unchanged [OK]
- Swapping when parent is already largest
- Confusing indices of children
- Assuming heapify sorts entire array
void Heapify(int[] arr, int n, int i) {
int largest = i;
int left = 2 * i + 1;
int 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) {
int temp = arr[i];
arr[i] = arr[largest];
arr[largest] = temp;
Heapify(arr, n, largest);
}
}
What is the bug if the recursive call is missing?Solution
Step 1: Understand recursive call role
After swapping, heapify must be called on the affected child subtree to fix heap property there.Step 2: Effect of missing recursion
Without recursion, only the root node is fixed, subtrees may remain invalid heaps.Final Answer:
Heap property may not be restored in subtrees -> Option DQuick Check:
Missing recursion breaks heap property below swapped node [OK]
- Assuming one swap fixes entire heap
- Thinking missing recursion causes crash
- Ignoring subtree heap violations
[3, 9, 2, 1, 4, 5]. After building a max-heap using the heapify method from the bottom up, what is the final array?Solution
Step 1: Start heapify from last non-leaf node
Last non-leaf node index = (6/2)-1 = 2. Heapify at index 2 (value 2): children 5 (index 5), no right child. Swap 2 and 5 -> [3,9,5,1,4,2]Step 2: Heapify at index 1 (value 9)
Children 1 (index 3), 4 (index 4). 9 is largest, no change -> [3,9,5,1,4,2]Step 3: Heapify at index 0 (value 3)
Children 9 (index 1), 5 (index 2). Largest is 9, swap 3 and 9 -> [9,3,5,1,4,2]. Now heapify at index 1 (value 3): children 1 and 4. Largest is 4, swap 3 and 4 -> [9,4,5,1,3,2]Final Answer:
[9, 4, 5, 1, 3, 2] -> Option BQuick Check:
Bottom-up heapify gives max-heap [OK]
- Not heapifying all non-leaf nodes
- Swapping incorrectly with children
- Stopping heapify too early
Ready to prove it?
Pass the test and this pattern moves unknown
