|
| 1 | +<h1 align='center'>Smallest - Range - in K - Lists</h1> |
| 2 | + |
| 3 | +## Problem Statement |
| 4 | + |
| 5 | +**Problem URL :** [Smallest Range in K Lists](https://www.geeksforgeeks.org/problems/find-smallest-range-containing-elements-from-k-lists/1) |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | + |
| 10 | +## Problem Explanation |
| 11 | +The task is to find the smallest range that includes at least one element from each of the `k` sorted lists (arrays). The range is defined as `[start, end]`, where: |
| 12 | +- `start` is the smallest number in the range. |
| 13 | +- `end` is the largest number in the range. |
| 14 | + |
| 15 | +**Example:** |
| 16 | +```plaintext |
| 17 | +Input: |
| 18 | +k = 3, n = 5 |
| 19 | +arr = [[4, 7, 9, 12, 15], |
| 20 | + [0, 8, 10, 14, 20], |
| 21 | + [6, 12, 16, 30, 50]] |
| 22 | +
|
| 23 | +Output: |
| 24 | +[6, 8] |
| 25 | +Explanation: |
| 26 | +- The range `[6, 8]` contains at least one element from each list: |
| 27 | + - From the first list: 7 |
| 28 | + - From the second list: 8 |
| 29 | + - From the third list: 6 |
| 30 | +``` |
| 31 | + |
| 32 | + |
| 33 | + |
| 34 | +#### **Approach:** |
| 35 | +We use a **min-heap** (priority queue) to solve this problem. The algorithm works as follows: |
| 36 | + |
| 37 | +1. **Initialization:** |
| 38 | + - Start by adding the first element of each list to the min-heap. |
| 39 | + - Track the minimum (`mini`) and maximum (`maxi`) values among the elements in the heap. |
| 40 | + |
| 41 | +2. **Range Calculation:** |
| 42 | + - The current range is `[mini, maxi]`. |
| 43 | + - As we process the heap, check if the current range is smaller than the previous range. If it is, update the range. |
| 44 | + |
| 45 | +3. **Heap Operations:** |
| 46 | + - Remove the smallest element (`mini`) from the heap. |
| 47 | + - Add the next element from the same list to the heap. |
| 48 | + - Update `mini` and `maxi`. |
| 49 | + |
| 50 | +4. **Termination:** |
| 51 | + - Stop when any of the lists is exhausted, as we can no longer include an element from every list. |
| 52 | + |
| 53 | +## Problem Solution |
| 54 | +```cpp |
| 55 | +class Node{ |
| 56 | + public: |
| 57 | + int data; |
| 58 | + int row; |
| 59 | + int col; |
| 60 | + |
| 61 | + Node(int data, int row, int col){ |
| 62 | + this -> data = data; |
| 63 | + this -> row = row; |
| 64 | + this -> col = col; |
| 65 | + } |
| 66 | +}; |
| 67 | + |
| 68 | +class compare{ |
| 69 | + public: |
| 70 | + bool operator()(Node* a, Node* b){ |
| 71 | + return a -> data > b -> data; |
| 72 | + } |
| 73 | +}; |
| 74 | +class Solution{ |
| 75 | + public: |
| 76 | + pair<int,int> findSmallestRange(int arr[][N], int n, int k) |
| 77 | + { |
| 78 | + int mini = INT_MAX; |
| 79 | + int maxi = INT_MIN; |
| 80 | + |
| 81 | + priority_queue<Node*, vector<Node*>, compare> minHeap; |
| 82 | + |
| 83 | + for(int i = 0; i < k; i++){ |
| 84 | + int element = arr[i][0]; |
| 85 | + |
| 86 | + mini = min(mini, element); |
| 87 | + maxi = max(maxi, element); |
| 88 | + |
| 89 | + minHeap.push(new Node(element, i, 0)); |
| 90 | + } |
| 91 | + |
| 92 | + |
| 93 | + int start = mini, end = maxi; |
| 94 | + |
| 95 | + while(!minHeap.empty()){ |
| 96 | + Node* temp = minHeap.top(); |
| 97 | + minHeap.pop(); |
| 98 | + |
| 99 | + mini = temp -> data; |
| 100 | + |
| 101 | + if(maxi - mini < end - start){ |
| 102 | + start = mini; |
| 103 | + end = maxi; |
| 104 | + } |
| 105 | + |
| 106 | + if(temp -> col + 1 < n){ |
| 107 | + maxi = max(maxi, arr[temp->row][temp->col + 1]); |
| 108 | + minHeap.push(new Node(arr[temp->row][temp->col + 1], temp -> row, temp -> col + 1)); |
| 109 | + }else break; |
| 110 | + |
| 111 | + } |
| 112 | + |
| 113 | + return {start, end}; |
| 114 | + |
| 115 | + } |
| 116 | +}; |
| 117 | +``` |
| 118 | +
|
| 119 | +## Problem Solution Explanation |
| 120 | +
|
| 121 | +1. **Node Class:** |
| 122 | + ```cpp |
| 123 | + class Node { |
| 124 | + public: |
| 125 | + int data; |
| 126 | + int row; |
| 127 | + int col; |
| 128 | + |
| 129 | + Node(int data, int row, int col) { |
| 130 | + this->data = data; |
| 131 | + this->row = row; |
| 132 | + this->col = col; |
| 133 | + } |
| 134 | + }; |
| 135 | + ``` |
| 136 | + - The `Node` class is used to store three pieces of information: |
| 137 | + - `data`: The value of the current element. |
| 138 | + - `row`: The row index of the element (corresponding to the list it belongs to). |
| 139 | + - `col`: The column index of the element in its row. |
| 140 | + |
| 141 | +2. **Custom Comparator:** |
| 142 | + ```cpp |
| 143 | + class compare { |
| 144 | + public: |
| 145 | + bool operator()(Node* a, Node* b) { |
| 146 | + return a->data > b->data; |
| 147 | + } |
| 148 | + }; |
| 149 | + ``` |
| 150 | + - This comparator defines the priority for the heap. |
| 151 | + - It ensures the heap works as a **min-heap**, with the smallest element at the top. |
| 152 | +
|
| 153 | +3. **Initialization:** |
| 154 | + ```cpp |
| 155 | + priority_queue<Node*, vector<Node*>, compare> minHeap; |
| 156 | + int mini = INT_MAX; |
| 157 | + int maxi = INT_MIN; |
| 158 | + ``` |
| 159 | + - `minHeap`: Stores the smallest elements across all lists. |
| 160 | + - `mini` and `maxi`: Track the smallest and largest values in the current range. |
| 161 | + |
| 162 | +4. **Push Initial Elements into the Heap:** |
| 163 | + ```cpp |
| 164 | + for (int i = 0; i < k; i++) { |
| 165 | + int element = arr[i][0]; |
| 166 | + mini = min(mini, element); |
| 167 | + maxi = max(maxi, element); |
| 168 | + minHeap.push(new Node(element, i, 0)); |
| 169 | + } |
| 170 | + ``` |
| 171 | + - For each list, add its first element to the heap. |
| 172 | + - Update `mini` and `maxi` to reflect the smallest and largest values. |
| 173 | +
|
| 174 | +5. **Track the Best Range:** |
| 175 | + ```cpp |
| 176 | + int start = mini, end = maxi; |
| 177 | + ``` |
| 178 | + - Initialize the range `[start, end]` with the initial `mini` and `maxi`. |
| 179 | + |
| 180 | +6. **Process the Min-Heap:** |
| 181 | + ```cpp |
| 182 | + while (!minHeap.empty()) { |
| 183 | + Node* temp = minHeap.top(); |
| 184 | + minHeap.pop(); |
| 185 | + mini = temp->data; |
| 186 | + |
| 187 | + if (maxi - mini < end - start) { |
| 188 | + start = mini; |
| 189 | + end = maxi; |
| 190 | + } |
| 191 | + |
| 192 | + if (temp->col + 1 < n) { |
| 193 | + int nextElement = arr[temp->row][temp->col + 1]; |
| 194 | + maxi = max(maxi, nextElement); |
| 195 | + minHeap.push(new Node(nextElement, temp->row, temp->col + 1)); |
| 196 | + } else { |
| 197 | + break; |
| 198 | + } |
| 199 | + } |
| 200 | + ``` |
| 201 | + - Extract the smallest element (`mini`) from the heap. |
| 202 | + - Check if the current range `[mini, maxi]` is smaller than `[start, end]`. |
| 203 | + - Add the next element from the same list to the heap, and update `maxi`. |
| 204 | + - Stop if any list is exhausted. |
| 205 | +
|
| 206 | +7. **Return the Result:** |
| 207 | + ```cpp |
| 208 | + return {start, end}; |
| 209 | + ``` |
| 210 | + - Return the smallest range `[start, end]`. |
| 211 | + |
| 212 | + |
| 213 | + |
| 214 | +### Step 3: Examples and Explanation |
| 215 | + |
| 216 | +#### Example 1: |
| 217 | +```plaintext |
| 218 | +Input: |
| 219 | +k = 3, n = 5 |
| 220 | +arr = [[4, 7, 9, 12, 15], |
| 221 | + [0, 8, 10, 14, 20], |
| 222 | + [6, 12, 16, 30, 50]] |
| 223 | +
|
| 224 | +Output: |
| 225 | +[6, 8] |
| 226 | +``` |
| 227 | +**Execution Steps:** |
| 228 | +1. Initialize heap: `[4, 0, 6]`, `mini = 0`, `maxi = 6`. |
| 229 | +2. Extract `mini = 0`, add `7` to the heap: `[4, 6, 7]`, `maxi = 7`. |
| 230 | +3. Extract `mini = 4`, add `8` to the heap: `[6, 7, 8]`, `maxi = 8`. |
| 231 | +4. Extract `mini = 6`, update range `[6, 8]`. |
| 232 | + |
| 233 | + |
| 234 | + |
| 235 | +### Step 4: Time and Space Complexity |
| 236 | + |
| 237 | +#### **Time Complexity:** |
| 238 | +- **Heap Operations:** Each insertion and deletion in the heap takes \(O(\log k)\), where \(k\) is the number of lists. |
| 239 | +- **Total Elements Processed:** \(n \times k\) elements are processed (each list has \(n\) elements). |
| 240 | +- **Overall:** \(O(n \times k \times \log k)\). |
| 241 | + |
| 242 | +#### **Space Complexity:** |
| 243 | +- The heap stores at most \(k\) elements at any time: \(O(k)\). |
| 244 | +- Additional space for the `Node` objects: \(O(k)\). |
| 245 | +- **Overall:** \(O(k)\). |
| 246 | + |
| 247 | + |
| 248 | + |
| 249 | +### Step 5: Recommendations for Students |
| 250 | +1. **Understand the Min-Heap:** |
| 251 | + - Practice problems that involve heap data structures to solidify your understanding. |
| 252 | + - Implement custom comparators and understand their use cases. |
| 253 | + |
| 254 | +2. **Optimize for Edge Cases:** |
| 255 | + - Test with edge cases like single-element lists or lists with duplicate elements. |
| 256 | + |
| 257 | +3. **Debugging Tips:** |
| 258 | + - Print the heap contents at each step to debug and understand the flow. |
| 259 | + |
| 260 | +By practicing such problems, you'll develop skills in working with advanced data structures like heaps and improve problem-solving efficiency! |
0 commit comments