diff --git a/README.md b/README.md index 5ca4ee8..521ca11 100644 --- a/README.md +++ b/README.md @@ -30,6 +30,7 @@ My LeetCode solutions with Chinese explanation. 我的LeetCode中文题解。 | 20 |[Valid Parentheses](https://leetcode.com/problems/valid-parentheses)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/20.%20Valid%20Parentheses.md)|Easy| | | 21 |[Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/21.%20Merge%20Two%20Sorted%20Lists.md)|Easy| | | 22 |[Generate Parentheses](https://leetcode.com/problems/generate-parentheses)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/22.%20Generate%20Parentheses.md)|Medium| | +| 23 |[Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/)|[C++](solutions/23.%20Merge%20k%20Sorted%20Lists.md)|Hard| | | 24 |[Swap Nodes in Pairs](https://leetcode.com/problems/swap-nodes-in-pairs)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/24.%20Swap%20Nodes%20in%20Pairs.md)|Medium| | | 26 |[Remove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/26.%20Remove%20Duplicates%20from%20Sorted%20Array.md)|Easy| | | 27 |[Remove Element](https://leetcode.com/problems/remove-element)|[C++](https://github.com/ShusenTang/LeetCode/blob/master/solutions/27.%20Remove%20Element.md)|Easy| | diff --git a/solutions/23. Merge k Sorted Lists.md b/solutions/23. Merge k Sorted Lists.md new file mode 100644 index 0000000..49066f4 --- /dev/null +++ b/solutions/23. Merge k Sorted Lists.md @@ -0,0 +1,131 @@ +# [23. Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/) + +# 思路 + +将k个排好序的链表合并成一个大的有序链表。 + +## 思路一 + +最好想的就是维护一个堆(priority_queue)或者红黑树(multiset或者multimap)的数据结构。首先把k个链表的首元素都加入其中,然后每次取出最小的那个元素加入最终结果的链表中,然后把取出元素所在链表的下一个元素再加入结构中,以此类推,直到结构中没有元素了。 + + +设所有元素个数为N,时间复杂度O(Nlogk),空间复杂度O(k) + +## 思路二 + +另一个思路就是外排序,即k路归并排序的思想,如下图所示 + +
+image_name +
+ +由于每次归并时间复杂度是线性的,所以每一轮归并时间均为O(N),而需要 logk 轮归并,所以时间复杂度O(Nlogk)。 + +空间复杂度O(1) + +# C++ +## 思路一、使用priority_queue +**注意学习如何自定义compare类** +``` C++ +// 默认为最大堆, 所以需要自定义compare类使成为最小堆 +struct compare { + bool operator()(const ListNode* p1, const ListNode* p2) { + return p1 -> val > p2 -> val; + } +}; + +class Solution { +public: + ListNode* mergeKLists(vector& lists) { + priority_queue, compare>min_heap; + + for(int i = 0; i < lists.size(); i++) + if(lists[i]) min_heap.push(lists[i]); + + if(min_heap.empty()) return NULL; + + ListNode *head = min_heap.top(), *p = head; + min_heap.pop(); + if(p -> next) min_heap.push(p -> next); + while(!min_heap.empty()){ + p -> next = min_heap.top(); min_heap.pop(); + p = p -> next; + if(p -> next) min_heap.push(p -> next); + } + return head; + } +}; +``` + +## 思路一、使用multimap +**注意multimap插入时需传入一个{key, value}的pair** +``` C++ +class Solution { +public: + ListNode* mergeKLists(vector& lists) { + multimapmp; + for(int i = 0; i < lists.size(); i++) + if(lists[i]) mp.insert({lists[i] -> val, lists[i]}); + + if(mp.empty()) return NULL; + + ListNode *head = mp.begin() -> second, *p = head; + mp.erase(mp.begin()); + if(p -> next) mp.insert({p -> next -> val, p -> next}); + while(!mp.empty()){ + p -> next = mp.begin() -> second; + mp.erase(mp.begin()); + p = p -> next; + if(p -> next) mp.insert({p -> next-> val, p -> next}); + } + return head; + } +}; +``` + +## 思路二 +``` C++ +class Solution { +private: + ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { + /*copy from 21. Merge Two Sorted Lists */ + ListNode *res = new ListNode(0); + ListNode *pre = res; + while(l1 && l2){ + if(l1 -> val <= l2 -> val){ + pre -> next = l1; + l1 = l1 -> next; + } + else{ + pre -> next = l2; + l2 = l2 -> next; + } + pre = pre -> next; + } + + if(l1) pre -> next = l1; + else pre -> next = l2; + + ListNode *head = res; + res = head -> next; + head -> next = NULL; + delete head; + return res; + } + +public: + ListNode* mergeKLists(vector& lists) { + int n = lists.size(); + if(!n) return NULL; + + int interval = 1; + while(interval < n){ + for(int i = 0; i < n - interval; i += (2 * interval)) + lists[i] = mergeTwoLists(lists[i], lists[i+interval]); + + interval*=2; + } + return lists[0]; + } +}; +``` \ No newline at end of file diff --git a/solutions/img/23.png b/solutions/img/23.png new file mode 100644 index 0000000..4e14a74 Binary files /dev/null and b/solutions/img/23.png differ