Problem Statement
Given a min-heap in array representation named nums
, convert it into a max-heap and return the resulting array.
A min-heap is a complete binary tree where the key at the root is the minimum among all keys present in a binary min-heap and the same property is recursively true for all nodes in the Binary Tree.
A max-heap is a complete binary tree where the key at the root is the maximum among all keys present in a binary max-heap and the same property is recursively true for all nodes in the Binary Tree.
Examples
Example 1:
Input: nums = [10, 20, 30, 21, 23]
Output: [30, 21, 23, 10, 20]
Example 2:
Input: nums = [-5, -4, -3, -2, -1]
Output: [-1, -2, -3, -4, -5]
Different Approaches
1️⃣ Heapify-Down
Intution:
This problem is similar to building heap from a given array. The fact that the given array is a min-heap array can be overlooked, boiling down the problem to building a Max-heap array from the given array.
Approach:
- Start from the last non-leaf node in the array, as leaf nodes are already min-heaps.
- Perform a downward heapify operation on each node, ensuring the max-heap property (the parent must be larger than its children) is maintained.
- The heapify operation compares the current node with its children, swaps it with the larger child if necessary, and recursively heapifies the affected subtree.
- Once the iterations are over, the given array is converted into a max-heap.
Code:
#include <bits/stdc++.h>
using namespace std;
class Solution {
private:
// Function to recursively heapify the array downwards
void heapifyDown(vector<int> &arr, int ind) {
int n = arr.size(); // Size of the array
// To store the index of largest element
int largestInd = ind;
// Indices of the left and right children
int leftChildInd = 2*ind + 1, rightChildInd = 2*ind + 2;
// If the left child holds larger value, update the largest index
if(leftChildInd < n && arr[leftChildInd] > arr[largestInd])
largestInd = leftChildInd;
// If the right child holds larger value, update the largest index
if(rightChildInd < n && arr[rightChildInd] > arr[largestInd])
largestInd = rightChildInd;
// If the largest element index is updated
if(largestInd != ind) {
// Swap the largest element with the current index
swap(arr[largestInd] , arr[ind]);
// Recursively heapify the lower subtree
heapifyDown(arr, largestInd);
}
return;
}
public:
// Function to convert a min-heap array to a max-heap array
vector<int> minToMaxHeap(vector<int> nums) {
int n = nums.size();
// Iterate backwards on the non-leaf nodes
for(int i = n/2 - 1; i >= 0; i--) {
// Heapify each node downwards
heapifyDown(nums, i);
}
return nums;
}
};
// Driver code
int main() {
vector<int> nums = {10, 20, 30, 21, 23};
cout << "Initial Min-heap Array: ";
for(int x : nums) cout << x << " ";
// Creating an object of the Solution class
Solution sol;
// Function call to convert a min-heap array to a max-heap array
nums = sol.minToMaxHeap(nums);
cout << "\nMax-heap converted Array: ";
for(int x : nums) cout << x << " ";
return 0;
}
Complexity Analysis:
- Time Complexity:
O(N)
(where N is the number of elements in the array)- Each heapify call has a time complexity of O(h), where h is the height of the subtree, h = log(N). The heapify operation is performed for approximately N/2 non-leaf nodes.
- Due the variable height for all the subtrees, summing the total work done for all the nodes results in an overall time complexity of O(N) for building a heap.
- Space Complexity:
O(logN)
- The recursive calls during heapify require stack space proportional to the height of the heap which will be of the order of log(N) in the worst-case.