Given an array nums representing a min-heap and two integers ind and val, set the value at index ind (0-based) to val and perform the heapify algorithm such that the resulting array follows the min-heap property.
Modify the original array in-place, no need to return anything.
When a value is updated at a particular index, the array following the min-heap property consistently gets distorted. To make the array consistent again, the heapify algorithm is used.
When a particular index value is updated, there can be two cases:
#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
// Index of largest element
int largest_Ind = ind;
// Indices of the left and right children
int leftChild_Ind = 2*ind + 1, rightChild_Ind = 2*ind + 2;
// If the left child holds larger value, update the largest index
if(leftChild_Ind < n && arr[leftChild_Ind] < arr[largest_Ind])
largest_Ind = leftChild_Ind;
// If the right child holds larger value, update the largest index
if(rightChild_Ind < n && arr[rightChild_Ind] < arr[largest_Ind])
largest_Ind = rightChild_Ind;
// If the largest element index is updated
if(largest_Ind != ind) {
// Swap the largest element with the current index
swap(arr[largest_Ind] , arr[ind]);
// Recursively heapify the lower subtree
heapifyDown(arr, largest_Ind);
}
return;
}
// Function to recursively heapify the array upwards
void heapifyUp(vector<int> &arr, int ind) {
int parent_Ind = (ind - 1)/2;
// If current index holds greater value than the parent
if(ind > 0 && arr[ind] < arr[parent_Ind]) {
// Swap the values at the two indices
swap(arr[ind], arr[parent_Ind]);
// Recursively heapify the upper nodes
heapifyUp(arr, parent_Ind);
}
return;
}
public:
// Function to implement the heapify algorithm for a min-heap
void heapify(vector<int> &nums, int ind, int val) {
// If the current value is replaced with a smaller value
if(nums[ind] > val) {
nums[ind] = val;
heapifyUp(nums, ind);
}
// Else if the current value is replaced with a larger value
else {
nums[ind] = val;
heapifyDown(nums, ind);
}
return;
}
};
// Driver code
int main() {
vector<int> nums = {1, 4, 5, 5, 7, 6};
int ind = 5, val = 2;
// Input array
cout << "Input array: ";
for(int it : nums) cout << it << " ";
// Creating an object of the Solution class
Solution sol;
// Function call to heapify the array
sol.heapify(nums, ind, val);
// Output array
cout << "\nModified array after heapifying: ";
for(int it : nums) cout << it << " ";
return 0;
}import java.util.*;
class Solution {
// Function to recursively heapify the array downwards
private void heapifyDown(int[] arr, int ind) {
int n = arr.length; // Size of the array
// Index of largest element
int largest_Ind = ind;
// Indices of the left and right children
int leftChild_Ind = 2 * ind + 1, rightChild_Ind = 2 * ind + 2;
// If the left child holds a larger value, update the largest index
if (leftChild_Ind < n && arr[leftChild_Ind] < arr[largest_Ind])
largest_Ind = leftChild_Ind;
// If the right child holds a larger value, update the largest index
if (rightChild_Ind < n && arr[rightChild_Ind] < arr[largest_Ind])
largest_Ind = rightChild_Ind;
// If the largest element index is updated
if (largest_Ind != ind) {
// Swap the largest element with the current index
int temp = arr[largest_Ind];
arr[largest_Ind] = arr[ind];
arr[ind] = temp;
// Recursively heapify the lower subtree
heapifyDown(arr, largest_Ind);
}
return;
}
// Function to recursively heapify the array upwards
private void heapifyUp(int[] arr, int ind) {
int parent_Ind = (ind - 1) / 2;
// If current index holds a greater value than the parent
if (ind > 0 && arr[ind] < arr[parent_Ind]) {
// Swap the values at the two indices
int temp = arr[ind];
arr[ind] = arr[parent_Ind];
arr[parent_Ind] = temp;
// Recursively heapify the upper nodes
heapifyUp(arr, parent_Ind);
}
return;
}
// Function to implement the heapify algorithm for a min-heap
public void heapify(int[] nums, int ind, int val) {
// If the current value is replaced with a smaller value
if (nums[ind] > val) {
nums[ind] = val;
heapifyUp(nums, ind);
}
// Else if the current value is replaced with a larger value
else {
nums[ind] = val;
heapifyDown(nums, ind);
}
return;
}
}
class Main {
// Main method
public static void main(String[] args) {
int[] nums = {1, 4, 5, 5, 7, 6};
int ind = 5, val = 2;
// Input array
System.out.println("Input array: " + Arrays.toString(nums));
// Creating an object of the Solution class
Solution sol = new Solution();
// Function call to heapify the array
sol.heapify(nums, ind, val);
// Output array
System.out.println("Modified array after heapifying: " + Arrays.toString(nums));
}
}class Solution:
# Function to recursively heapify the array downwards
def heapifyDown(self, arr, ind):
n = len(arr) # Size of the array
# Index of largest element
largest_Ind = ind
# Indices of the left and right children
leftChild_Ind, rightChild_Ind = 2 * ind + 1, 2 * ind + 2
# If the left child holds a larger value, update the largest index
if leftChild_Ind < n and arr[leftChild_Ind] < arr[largest_Ind]:
largest_Ind = leftChild_Ind
# If the right child holds a larger value, update the largest index
if rightChild_Ind < n and arr[rightChild_Ind] < arr[largest_Ind]:
largest_Ind = rightChild_Ind
# If the largest element index is updated
if largest_Ind != ind:
# Swap the largest element with the current index
arr[largest_Ind], arr[ind] = arr[ind], arr[largest_Ind]
# Recursively heapify the lower subtree
self.heapifyDown(arr, largest_Ind)
return
# Function to recursively heapify the array upwards
def heapifyUp(self, arr, ind):
parent_Ind = (ind - 1) // 2
# If current index holds a greater value than the parent
if ind > 0 and arr[ind] < arr[parent_Ind]:
# Swap the values at the two indices
arr[ind], arr[parent_Ind] = arr[parent_Ind], arr[ind]
# Recursively heapify the upper nodes
self.heapifyUp(arr, parent_Ind)
return
# Function to implement the heapify algorithm for a min-heap
def heapify(self, nums, ind, val):
# If the current value is replaced with a smaller value
if nums[ind] > val:
nums[ind] = val
self.heapifyUp(nums, ind)
# Else if the current value is replaced with a larger value
else:
nums[ind] = val
self.heapifyDown(nums, ind)
return
# Driver code
if __name__ == "__main__":
nums = [1, 4, 5, 5, 7, 6]
ind, val = 5, 2
# Input array
print("Input array:", nums)
# Creating an object of the Solution class
sol = Solution()
# Function call to heapify the array
sol.heapify(nums, ind, val)
# Output array
print("Modified array after heapifying:", nums)class Solution {
// Function to recursively heapify the array downwards
heapifyDown(arr, ind) {
const n = arr.length; // Size of the array
// Index of largest element
let largest_Ind = ind;
// Indices of the left and right children
const leftChild_Ind = 2 * ind + 1, rightChild_Ind = 2 * ind + 2;
// If the left child holds a larger value, update the largest index
if (leftChild_Ind < n && arr[leftChild_Ind] < arr[largest_Ind])
largest_Ind = leftChild_Ind;
// If the right child holds a larger value, update the largest index
if (rightChild_Ind < n && arr[rightChild_Ind] < arr[largest_Ind])
largest_Ind = rightChild_Ind;
// If the largest element index is updated
if (largest_Ind !== ind) {
// Swap the largest element with the current index
[arr[largest_Ind], arr[ind]] = [arr[ind], arr[largest_Ind]];
// Recursively heapify the lower subtree
this.heapifyDown(arr, largest_Ind);
}
return;
}
// Function to recursively heapify the array upwards
heapifyUp(arr, ind) {
const parent_Ind = Math.floor((ind - 1) / 2);
// If current index holds a greater value than the parent
if (ind > 0 && arr[ind] < arr[parent_Ind]) {
// Swap the values at the two indices
[arr[ind], arr[parent_Ind]] = [arr[parent_Ind], arr[ind]];
// Recursively heapify the upper nodes
this.heapifyUp(arr, parent_Ind);
}
return;
}
// Function to implement the heapify algorithm for a min-heap
heapify(nums, ind, val) {
// If the current value is replaced with a smaller value
if (nums[ind] > val) {
nums[ind] = val;
this.heapifyUp(nums, ind);
}
// Else if the current value is replaced with a larger value
else {
nums[ind] = val;
this.heapifyDown(nums, ind);
}
return;
}
}
// Driver code
const nums = [1, 4, 5, 5, 7, 6];
const ind = 5, val = 2;
// Input array
console.log("Input array:", nums);
// Creating an object of the Solution class
const sol = new Solution();
// Function call to heapify the array
sol.heapify(nums, ind, val);
// Output array
console.log("Modified array after heapifying:", nums);
Time Complexity: O(log2N) (where N is the number of elements of the array)
The heapify function calls either heapifyUp or heapifyDown, both of which in the worst case will make number of recursive calls equal to the height of the heap which is log2N.
Space Complexity: O(log2N)
The recursive stack space will contribute to log2N in the worst-case. There is no extra space used other than this as the array is modified in-place.
Q: Why do we sometimes heapify up and sometimes heapify down?
A: If the new value is smaller, it may violate the parent rule → heapify up. If the new value is larger, it may violate the child rule → heapify down.
Q: What if we set a value but the heap remains valid?
A: If the new value does not violate heap rules, no changes are required.
Q: How can we optimize updates if they happen frequently?
A: Use a Fibonacci Heap or Lazy Heap Updates to batch modifications and reduce complexity.
Q: How would you implement this if the heap was stored in a different data structure (e.g., linked list)?
A: Heapify operations rely on indexed access, so arrays are the best choice. Using a linked list would increase traversal time to O(n) instead of O(log n).