Hello! Let's dive into our next lesson on heaps.
In our last session, we implemented a binary heap from the ground up. We learned how to insert elements one by one, using an upheap operation (percolateUp), and how to extract the root element using a downheap operation (percolateDown). While inserting N elements one by one is a valid way to build a heap, it takes time in total.
Today, we'll learn a more efficient method. When you're given an entire collection of items upfront, you can build a heap in-place much faster. Your learning outcome is to build a heap from an unordered array in linear time using the heapify-down operation. This is a classic and highly efficient algorithm, frequently asked about in interviews and essential for implementing Heap Sort.
1. Two Approaches to Building a Heap
Imagine you have an array of numbers, say [4, 1, 3, 2, 16, 9, 10, 14, 8, 7]. How would you turn this into a max-heap?
-
One-by-one Insertion (): You could start with an empty heap and insert each element from the array. The first insertion is cheap, but as the heap grows, each subsequent insertion can take up to time, where
kis the current size of the heap. Summing this over allNelements gives a total time complexity of . -
The
buildHeapAlgorithm (): A much faster way is to treat the entire array as a complete (but not yet valid) binary tree and then fix it. This process is often called "heapifying" the array.
Let's watch a short video that contrasts these two methods and sets the stage for the efficient buildHeap algorithm.
HeapSort | Heapify method to build a MaxHeap in O(n) | DSA-One Course #32
The video 'HeapSort | Heapify method...' by Anuj Kumar Sharma provides a clear introduction to the two methods of heap creation.
Watch from the beginning to 03:33. Notice the complexity of inserting elements one by one, and then see the introduction to the more efficient 'heapify' algorithm which we will explore in detail.
As you saw, the heapify approach promises a linear time complexity, which is a significant improvement. Let's see how it works.
2. The buildHeap Algorithm: Bottom-Up Heapifying
The core idea behind the efficient buildHeap algorithm is surprisingly simple:
- A leaf node, by itself, is a valid heap of size one.
- Therefore, we only need to worry about the non-leaf nodes.
Given an array of size n, we can view it as a complete binary tree. The leaf nodes occupy the second half of the array. Specifically, in a 0-indexed array, the last non-leaf node is at index (n/2) - 1.
The algorithm proceeds as follows:
- Start at the last non-leaf node: index
i = (n/2) - 1. - Call the
siftDown(orpercolateDown) function on the element at indexi. This ensures that the subtree rooted atibecomes a valid heap. Crucially, when we do this, the children ofiare already roots of valid heaps (since we are moving backwards from the leaves). - Decrement
iand repeat the process until you reach the root of the tree (index 0).
After siftDown has been called on the root, the entire array will satisfy the heap property.

Let's watch a detailed walkthrough of this process.
HeapSort | Heapify method to build a MaxHeap in O(n) | DSA-One Course #32
Anuj Kumar Sharma's video provides an excellent, step-by-step visualization of the heapify process.
Watch from 03:33 to 09:41. Follow along as he starts from the last non-leaf node and works his way up to the root, applying the heapify (sift-down) operation at each step. Pay close attention to how the array is modified after each swap.
The siftDown operation is the same one we learned in the previous lesson for extractMax/extractMin. It takes a node, compares it with its children, and swaps it with the largest (for a max-heap) or smallest (for a min-heap) child if needed. The process repeats until the node is in its correct place.

3. Implementation in Java
The implementation of buildHeap is remarkably concise. It's a simple for loop that calls the siftDown method you've already seen.
Let's examine the code from the OpenDSA resource.
This article from OpenDSA provides the formal definition and a clear Java implementation of buildHeap.
First, read the section 'Building a Heap'. It describes the bottom-up strategy. Then, look at the Java code provided. Focus on the buildHeap() method. Notice its simplicity: it's just a loop that iterates from parent(n-1) down to 0, calling siftDown(i) at each step. You can refer to the siftDown implementation provided in the same code block to refresh your memory.
Here's what the buildHeap method typically looks like in Java for a heap stored in an ArrayList<T> named heap.
private void buildHeap() {
// Start from the last non-leaf node and go up to the root
for (int i = (heap.size() / 2) - 1; i >= 0; i--) {
siftDown(i);
}
}
This function would be called in the constructor if you were creating a heap from an existing collection.
Test your understanding!
You are given the array [10, 20, 5, 8, 30]. You want to build a max-heap.
- What is the size
nof the array? - What is the index of the last non-leaf node where you would start the
buildHeapprocess? - What will the array look like after the first
siftDownoperation is completed?
Show answer
- The size
nis 5. - The index of the last non-leaf node is
(n/2) - 1 = (5/2) - 1 = 2 - 1 = 1. We start at index 1. - The initial array is
[10, 20, 5, 8, 30]. ThebuildHeaploop starts ati=1. We callsiftDown(1)on the element20. Its children are at indices2*1+1=3(value8) and2*1+2=4(value30). Since30is the largest child and is greater than20, we swap them.
The array becomes[10, 30, 5, 8, 20]. This is the state after the firstsiftDownoperation. The next step in the loop would besiftDown(0).
4. Why is it O(N) Time? A Closer Look
At first glance, the complexity seems to be . After all, we have a loop that runs about N/2 times, and inside it, we call siftDown, which takes time in the worst case. So why is the total complexity linear?
The key is that siftDown rarely takes its worst-case time. The cost of siftDown on a node is proportional to the height of that node, not the height of the whole tree.
- Most nodes are at the bottom: In a complete binary tree, about half the nodes are leaves (height 0). They require 0 work.
- A quarter are one level up: About N/4 nodes are parents of leaves (height 1). They can only be sifted down by at most 1 level.
- An eighth are two levels up: About N/8 nodes have a height of 2. They can be sifted down by at most 2 levels.
- ...and so on. Only a single root node can be sifted down by the full height of the tree, .
The total work is the sum of the heights of all nodes. This sum turns out to be a series that converges to a value proportional to N. Therefore, the total time complexity is .
Let's hear a final, clear explanation of this analysis.
Introduction to Heap Data Structure + Priority Queue + Heapsort Tutorial
Kunal Kushwaha offers a good intuitive and mathematical breakdown of why the complexity is O(N).
Watch from 57:48 to 1:06:30. He first walks through the buildHeap logic and then addresses the time complexity, explaining why the initial N log N assumption is incorrect and providing the intuition for the linear time bound.
Conclusion
You've just mastered a fundamental and highly efficient algorithm. While building a heap via repeated insertions is intuitive, the buildHeap algorithm is the superior choice when you have all the data at once.
Key Takeaways:
- You can build a heap from an unordered array in linear time.
- The
buildHeapalgorithm works by treating the array as a complete binary tree and callingsiftDownon each non-leaf node. - The process iterates backwards, from the last non-leaf node (
(n/2) - 1) up to the root (index0). - This bottom-up approach works because by the time you
siftDowna nodei, the subtrees rooted at its children are already valid heaps. - The linear time complexity comes from the fact that most nodes are near the bottom of the tree and require very few swaps.
Preview of the Next Lesson:
Now that we have an efficient buildHeap method, we have the first major component for one of the most elegant sorting algorithms: Heap Sort. In the next lesson, we will combine buildHeap with the extractMax operation to sort an array in-place with an time complexity.