Skip to content

Commit cbf7156

Browse files
authored
Create README.md
1 parent b693ca0 commit cbf7156

File tree

1 file changed

+253
-0
lines changed
  • 19 - Heap Data Structure Problems/13 - Merge K Sorted Lists

1 file changed

+253
-0
lines changed
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
<h1 align='center'>Merge - K Sorted - Lists</h1>
2+
3+
## Problem Statement
4+
5+
**Problem URL :** [Merge K Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/)
6+
7+
![image](https://github.com/user-attachments/assets/b5d19c93-6807-4e16-8be7-40d355f8dfc8)
8+
![image](https://github.com/user-attachments/assets/bc565118-e475-4628-aeb1-ac9636422268)
9+
10+
## Problem Explanation
11+
Given `K` sorted linked lists, we need to merge them into a single sorted linked list. The final merged list should contain all nodes from the original lists in sorted order.
12+
13+
**Example**:
14+
Suppose we have the following 3 sorted linked lists:
15+
16+
- `List 1: 1 -> 4 -> 7`
17+
- `List 2: 2 -> 5 -> 8`
18+
- `List 3: 3 -> 6 -> 9`
19+
20+
After merging, the final sorted linked list should be:
21+
`1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9`
22+
23+
### Approach:
24+
25+
To solve this problem efficiently, we use a **Min-Heap (priority queue)**.
26+
27+
1. **Use a Min-Heap to Store List Heads**:
28+
- We add the head of each linked list to the min-heap.
29+
- The min-heap automatically sorts nodes based on their values, keeping the smallest value node at the top.
30+
31+
2. **Process the Heap Until Empty**:
32+
- Extract the smallest node from the heap and add it to the merged list.
33+
- If the extracted node has a next node, insert that next node into the min-heap.
34+
- Repeat this until all nodes have been processed, resulting in a fully merged sorted list.
35+
36+
This approach is efficient because the min-heap allows us to retrieve the smallest node in `O(log K)` time for each insertion and deletion.
37+
38+
## Problem Solution
39+
```cpp
40+
/**
41+
* Definition for singly-linked list.
42+
* struct ListNode {
43+
* int val;
44+
* ListNode *next;
45+
* ListNode() : val(0), next(nullptr) {}
46+
* ListNode(int x) : val(x), next(nullptr) {}
47+
* ListNode(int x, ListNode *next) : val(x), next(next) {}
48+
* };
49+
*/
50+
51+
class compare{
52+
public:
53+
bool operator()(ListNode* a, ListNode* b){
54+
return a -> val > b -> val;
55+
}
56+
};
57+
class Solution {
58+
public:
59+
ListNode* mergeKLists(vector<ListNode*>& lists) {
60+
priority_queue<ListNode*, vector<ListNode*>, compare> pq;
61+
62+
int k = lists.size();
63+
64+
if(k == 0) return NULL;
65+
for(int i = 0; i < k; i++) if(lists[i] != NULL) pq.push(lists[i]);
66+
67+
ListNode* head = NULL;
68+
ListNode* tail = NULL;
69+
70+
while(pq.size() > 0){
71+
ListNode* top = pq.top();
72+
pq.pop();
73+
74+
if(head == NULL){
75+
head = top;
76+
tail = top;
77+
}else{
78+
tail -> next = top;
79+
tail = top;
80+
}
81+
82+
if(top -> next != NULL) pq.push(top -> next);
83+
}
84+
85+
return head;
86+
}
87+
};
88+
```
89+
90+
## Problem Solution Explanation
91+
92+
```cpp
93+
/**
94+
* Definition for singly-linked list.
95+
* struct ListNode {
96+
* int val;
97+
* ListNode *next;
98+
* ListNode() : val(0), next(nullptr) {}
99+
* ListNode(int x) : val(x), next(nullptr) {}
100+
* ListNode(int x, ListNode *next) : val(x), next(next) {}
101+
* };
102+
*/
103+
104+
class compare{
105+
public:
106+
bool operator()(ListNode* a, ListNode* b){
107+
return a -> val > b -> val;
108+
}
109+
};
110+
```
111+
112+
1. **Explanation**:
113+
- The `compare` class is a custom comparator for the min-heap.
114+
- The `operator()` overload function returns `true` if `a` has a greater value than `b`. This ensures the min-heap orders nodes based on increasing values.
115+
116+
117+
118+
```cpp
119+
class Solution {
120+
public:
121+
ListNode* mergeKLists(vector<ListNode*>& lists) {
122+
priority_queue<ListNode*, vector<ListNode*>, compare> pq;
123+
```
124+
125+
2. **Explanation**:
126+
- `mergeKLists` is the main function that merges `K` sorted lists.
127+
- A min-heap `pq` is created with `ListNode*` pointers, and the `compare` class as the comparator.
128+
129+
130+
131+
```cpp
132+
int k = lists.size();
133+
134+
if(k == 0) return NULL;
135+
for(int i = 0; i < k; i++) if(lists[i] != NULL) pq.push(lists[i]);
136+
```
137+
138+
3. **Explanation**:
139+
- `k` is the number of lists.
140+
- If `k` is 0 (i.e., there are no lists), we return `NULL`.
141+
- We iterate over each list and push its head node into the min-heap if it’s not `NULL`.
142+
143+
144+
145+
```cpp
146+
ListNode* head = NULL;
147+
ListNode* tail = NULL;
148+
```
149+
150+
4. **Explanation**:
151+
- `head` will store the head of the merged list, and `tail` will help us append nodes to the merged list.
152+
153+
154+
155+
```cpp
156+
while(pq.size() > 0){
157+
ListNode* top = pq.top();
158+
pq.pop();
159+
```
160+
161+
5. **Explanation**:
162+
- We process nodes in the min-heap until it’s empty.
163+
- `top` stores the smallest node in the min-heap, and we remove it from the heap using `pop()`.
164+
165+
166+
167+
```cpp
168+
if(head == NULL){
169+
head = top;
170+
tail = top;
171+
}else{
172+
tail -> next = top;
173+
tail = top;
174+
}
175+
```
176+
177+
6. **Explanation**:
178+
- If `head` is `NULL`, it means this is the first node being added to our merged list, so we set both `head` and `tail` to `top`.
179+
- Otherwise, we append `top` to `tail->next` and update `tail` to point to this new node.
180+
181+
182+
183+
```cpp
184+
if(top -> next != NULL) pq.push(top -> next);
185+
}
186+
```
187+
188+
7. **Explanation**:
189+
- If the node `top` has a next node, we push `top->next` into the min-heap.
190+
- This step ensures that the heap always has the next smallest element from any list.
191+
192+
193+
194+
```cpp
195+
return head;
196+
}
197+
};
198+
```
199+
200+
8. **Explanation**:
201+
- Finally, we return `head`, which points to the start of the fully merged sorted linked list.
202+
203+
204+
205+
### Step 3: Example Walkthrough
206+
207+
**Example**:
208+
Input:
209+
```cpp
210+
lists = [
211+
List 1: 1 -> 4 -> 7,
212+
List 2: 2 -> 5 -> 8,
213+
List 3: 3 -> 6 -> 9
214+
]
215+
```
216+
217+
Process:
218+
1. Push the head of each list into the min-heap:
219+
- Min-heap contains: `[1, 2, 3]`
220+
221+
2. Pop the smallest element (`1`) from the heap, append it to the result list, and push its next node (`4`) to the heap:
222+
- Result list: `1`
223+
- Min-heap: `[2, 3, 4]`
224+
225+
3. Repeat until all nodes are processed:
226+
- After each step, the min-heap is rebalanced, and the smallest element is appended to the result list.
227+
228+
Final merged result:
229+
`1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9`
230+
231+
Output:
232+
`1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9`
233+
234+
235+
236+
### Step 4: Time and Space Complexity
237+
238+
1. **Time Complexity**:
239+
- Inserting and deleting nodes in a heap of size `K` takes `O(log K)` time.
240+
- There are `N` total nodes across all lists, so we perform `N` insertions and deletions.
241+
- The time complexity is therefore `O(N * log K)`.
242+
243+
2. **Space Complexity**:
244+
- The space complexity is `O(K)`, as the heap can contain up to `K` nodes at any time (one from each list).
245+
246+
### Step 5: Additional Recommendations
247+
248+
- **Understand the Priority Queue**: This solution is highly efficient because it leverages a min-heap. Practice using priority queues to get comfortable with their behavior.
249+
- **Practice Edge Cases**: Ensure you handle edge cases such as empty lists, a single list, or lists with only one element.
250+
- **Experiment with Larger Data Sets**: Testing with larger lists can give you a better sense of the efficiency of this approach and help identify potential optimizations.
251+
- **NOTE :** [Approach 2](https://github.com/JawadSher/DSA-LeetCode-GFG-Problems-Repository/tree/main/14%20-%20Linked%20List%20Data%20Structure%20Problems/01%20-%20Singly%20Linked%20List%20Problems/24%20-%20Merge%20K%20Sorted%20Linked%20Lists)
252+
253+
This explanation should provide a comprehensive understanding of the solution approach, code, and complexity analysis.

0 commit comments

Comments
 (0)