|
| 1 | +<h1 align='center'>Merge - Two - Binary - Max - Heaps</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [Merge Two Binary Max Heaps](https://www.geeksforgeeks.org/problems/merge-two-binary-max-heap0144/1) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | + |
| 11 | +## Problem Explanation |
| 12 | + |
| 13 | +**Problem Statement**: |
| 14 | +The task is to **merge two binary max-heaps** into a single max-heap. A binary max-heap is a complete binary tree where each node’s value is greater than or equal to its children’s values. The merged heap must satisfy both the **completeness** property and the **max-heap** property. |
| 15 | + |
| 16 | +Given two arrays `a` and `b` that represent two binary max-heaps of sizes `n` and `m`, we need to: |
| 17 | +1. Combine these arrays into a single array that represents the merged heap. |
| 18 | +2. Ensure the combined array satisfies the max-heap property. |
| 19 | + |
| 20 | +**Examples**: |
| 21 | +1. **Input**: |
| 22 | + ``` |
| 23 | + a = [10, 5, 6, 2] |
| 24 | + b = [8, 7, 3] |
| 25 | + ``` |
| 26 | + - **Merged Heap**: `[10, 8, 7, 5, 2, 6, 3]` |
| 27 | + |
| 28 | +2. **Input**: |
| 29 | + ``` |
| 30 | + a = [9, 4, 8] |
| 31 | + b = [6, 5] |
| 32 | + ``` |
| 33 | + - **Merged Heap**: `[9, 6, 8, 4, 5]` |
| 34 | + |
| 35 | +**Approach**: |
| 36 | +1. **Merge the Arrays**: |
| 37 | + - First, create a new array, `mergeHeap`, large enough to hold all elements from both arrays. |
| 38 | + - Copy all elements from `a` and `b` into `mergeHeap`. |
| 39 | + |
| 40 | +2. **Heapify the Merged Array**: |
| 41 | + - Use the `maxHeapify` function to rearrange elements in `mergeHeap` to satisfy the max-heap property. |
| 42 | + - Start heapifying from the last non-leaf node up to the root node, ensuring all parent nodes are larger than their children. |
| 43 | + |
| 44 | + |
| 45 | +## Problem Solution |
| 46 | +```cpp |
| 47 | +class Solution{ |
| 48 | + public: |
| 49 | + void maxHeapify(vector<int> &v, int n, int i){ |
| 50 | + int largest = i; |
| 51 | + int leftIndex = 2 * i + 1; |
| 52 | + int rightIndex = 2 * i + 2; |
| 53 | + |
| 54 | + if(leftIndex < n && v[largest] < v[leftIndex]) largest = leftIndex; |
| 55 | + if(rightIndex < n && v[largest] < v[rightIndex]) largest = rightIndex; |
| 56 | + |
| 57 | + if(largest != i){ |
| 58 | + swap(v[largest], v[i]); |
| 59 | + maxHeapify(v, n, largest); |
| 60 | + } |
| 61 | + } |
| 62 | + vector<int> mergeHeaps(vector<int> &a, vector<int> &b, int n, int m) { |
| 63 | + vector<int> mergeHeap(n + m); |
| 64 | + |
| 65 | + for(int i = 0; i < n; i++){ |
| 66 | + mergeHeap[i] = a[i]; |
| 67 | + } |
| 68 | + |
| 69 | + for(int i = 0; i < m; i++){ |
| 70 | + mergeHeap[n+i] = b[i]; |
| 71 | + } |
| 72 | + |
| 73 | + for(int i = m+n / 2 -1; i >= 0; i--){ |
| 74 | + |
| 75 | + maxHeapify(mergeHeap, n+m, i); |
| 76 | + } |
| 77 | + |
| 78 | + return mergeHeap; |
| 79 | + } |
| 80 | +}; |
| 81 | +``` |
| 82 | +
|
| 83 | +## Problem Solution Explanation |
| 84 | +
|
| 85 | +```cpp |
| 86 | +class Solution{ |
| 87 | +public: |
| 88 | + void maxHeapify(vector<int> &v, int n, int i){ |
| 89 | + int largest = i; |
| 90 | + int leftIndex = 2 * i + 1; |
| 91 | + int rightIndex = 2 * i + 2; |
| 92 | +``` |
| 93 | +- **`maxHeapify` Function**: A helper function to maintain the max-heap property. |
| 94 | + - `largest` is initially set to `i`, assuming `i` is the largest. |
| 95 | + - `leftIndex` and `rightIndex` calculate the indices of the left and right children of the node at index `i`. |
| 96 | + |
| 97 | +```cpp |
| 98 | + if(leftIndex < n && v[largest] < v[leftIndex]) largest = leftIndex; |
| 99 | + if(rightIndex < n && v[largest] < v[rightIndex]) largest = rightIndex; |
| 100 | +``` |
| 101 | +- Checks if the left and right children exist within bounds (`< n`) and if either child is larger than the current largest element. |
| 102 | +- Updates `largest` to the index of the largest element among `i`, `leftIndex`, and `rightIndex`. |
| 103 | + |
| 104 | +```cpp |
| 105 | + if(largest != i){ |
| 106 | + swap(v[largest], v[i]); |
| 107 | + maxHeapify(v, n, largest); |
| 108 | + } |
| 109 | + } |
| 110 | +``` |
| 111 | +- If `largest` is not `i`, it swaps the elements at `i` and `largest` to ensure the max-heap property. |
| 112 | +- Calls `maxHeapify` recursively to fix any violations in the subtree rooted at `largest`. |
| 113 | +
|
| 114 | +```cpp |
| 115 | + vector<int> mergeHeaps(vector<int> &a, vector<int> &b, int n, int m) { |
| 116 | + vector<int> mergeHeap(n + m); |
| 117 | + |
| 118 | + for(int i = 0; i < n; i++){ |
| 119 | + mergeHeap[i] = a[i]; |
| 120 | + } |
| 121 | + |
| 122 | + for(int i = 0; i < m; i++){ |
| 123 | + mergeHeap[n+i] = b[i]; |
| 124 | + } |
| 125 | +``` |
| 126 | +- **`mergeHeaps` Function**: The main function to merge two heaps. |
| 127 | + - Initializes `mergeHeap` with size `n + m`. |
| 128 | + - Copies elements from array `a` to `mergeHeap`. |
| 129 | + - Copies elements from array `b` into `mergeHeap` starting from index `n`. |
| 130 | + |
| 131 | +```cpp |
| 132 | + for(int i = m+n / 2 -1; i >= 0; i--){ |
| 133 | + maxHeapify(mergeHeap, n+m, i); |
| 134 | + } |
| 135 | + |
| 136 | + return mergeHeap; |
| 137 | + } |
| 138 | +}; |
| 139 | +``` |
| 140 | +- Starts heapifying from the last non-leaf node (`(m + n) / 2 - 1`) up to the root. |
| 141 | +- Calls `maxHeapify` for each node to restore the max-heap property. |
| 142 | +- Returns the `mergeHeap` array. |
| 143 | + |
| 144 | +### Step 3: Example Walkthrough |
| 145 | + |
| 146 | +1. **Example 1**: |
| 147 | + - **Input**: |
| 148 | + ``` |
| 149 | + a = [10, 5, 6, 2] |
| 150 | + b = [8, 7, 3] |
| 151 | + ``` |
| 152 | + - **Steps**: |
| 153 | + - **Merging Arrays**: `mergeHeap = [10, 5, 6, 2, 8, 7, 3]` |
| 154 | + - **Heapifying**: Starting from the last non-leaf node and moving up. |
| 155 | + - At index `2`: Heapify `[10, 5, 7, 2, 8, 6, 3]` |
| 156 | + - At index `1`: Heapify `[10, 8, 7, 5, 2, 6, 3]` |
| 157 | + - At index `0`: Heapify `[10, 8, 7, 5, 2, 6, 3]` |
| 158 | + - **Output**: `[10, 8, 7, 5, 2, 6, 3]` |
| 159 | +
|
| 160 | +2. **Example 2**: |
| 161 | + - **Input**: |
| 162 | + ``` |
| 163 | + a = [9, 4, 8] |
| 164 | + b = [6, 5] |
| 165 | + ``` |
| 166 | + - **Steps**: |
| 167 | + - **Merging Arrays**: `mergeHeap = [9, 4, 8, 6, 5]` |
| 168 | + - **Heapifying**: Starting from the last non-leaf node and moving up. |
| 169 | + - At index `1`: Heapify `[9, 6, 8, 4, 5]` |
| 170 | + - At index `0`: Heapify `[9, 6, 8, 4, 5]` |
| 171 | + - **Output**: `[9, 6, 8, 4, 5]` |
| 172 | +
|
| 173 | +### Step 4: Time and Space Complexity |
| 174 | +
|
| 175 | +- **Time Complexity**: |
| 176 | + - Copying elements from `a` and `b` into `mergeHeap` takes **O(n + m)**. |
| 177 | + - Heapifying the merged array (`mergeHeap`) with `maxHeapify` takes **O(n + m)**, as each call to `maxHeapify` has a logarithmic complexity of **O(log(n + m))** and it’s applied to every element. |
| 178 | + - Total time complexity: **O(n + m)**. |
| 179 | +
|
| 180 | +- **Space Complexity**: |
| 181 | + - **O(n + m)**, as we create a new array `mergeHeap` to store the elements of both heaps. |
| 182 | +
|
| 183 | +### Step 5: Additional Recommendations for Students |
| 184 | +
|
| 185 | +- **Practice** with different combinations of arrays to understand how heapification works. |
| 186 | +- **Understand Heap Structure**: Review how max-heaps are stored in arrays and how `leftIndex = 2 * i + 1` and `rightIndex = 2 * i + 2` access children nodes. |
| 187 | +- **Debugging Tip**: For large arrays, printing intermediate states of `mergeHeap` can help visualize the transformations. |
| 188 | +- **Further Exploration**: Practice merging heaps using priority queues to see different implementations and time complexities. |
0 commit comments