题目:
合并 k 个排序链表,返回合并后的排序链表。请分析和描述算法的复杂度。
示例:
输入:
[
1->4->5,
1->3->4,
2->6
]
输出: 1->1->2->3->4->4->5->6
解法:
方法一:顺序合并
可以想到一种最朴素的方法:用一个变量ans来维护以及合并的链表,第i次循环把第i个链表和ans合并,答案保存到ans中。
时间复杂度为O(n*K^2)。
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 ListNode *mergeTwoList(ListNode *l1, ListNode *l2) 12 { 13 if (NULL == l1 || NULL == l2) 14 { 15 return l1 ? l1 : l2; 16 } 17 ListNode *head; 18 ListNode *tail = head; 19 ListNode *aptr = l1; 20 ListNode *bptr = l2; 21 22 while (aptr && bptr) 23 { 24 if (aptr->val < bptr->val) 25 { 26 tail->next = aptr; 27 aptr = aptr->next; 28 } 29 else 30 { 31 tail->next = bptr; 32 bptr = bptr->next; 33 } 34 35 tail = tail->next; 36 } 37 38 tail->next = aptr ? aptr : bptr; 39 40 return head->next; 41 } 42 43 ListNode* mergeKLists(vector<ListNode*>& lists) 44 { 45 ListNode *ans = NULL; 46 for (size_t i = 0; i < lists.size(); i++) 47 { 48 ans = mergeTwoList(ans, lists[i]); 49 } 50 return ans; 51 } 52 };
方法二:
扫描二维码关注公众号,回复:
11164149 查看本文章
这个方法和之前方法思路有所不同,我们需要维护每个链表没有被合并的元素的最前面一个,k个链表就最多有k个满足这样条件的元素,每次在这些元素里面选取val属性最小的元素合并到答案中。在选取最小元素的时候,我们可以用优先队列来优化这个过程。
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 struct status 12 { 13 int val; 14 ListNode *ptr; 15 bool operator < (const status &rhs) const { 16 return val > rhs.val; 17 } 18 }; 19 20 priority_queue<status> q; 21 22 ListNode* mergeKLists(vector<ListNode*>& lists) 23 { 24 for (auto node: lists) 25 { 26 if (node) 27 { 28 q.push({node->val, node}); 29 } 30 } 31 ListNode head, *tail = &head; 32 while (!q.empty()) 33 { 34 auto f = q.top(); 35 q.pop(); 36 tail->next = f.ptr; 37 tail = tail->next; 38 if (f.ptr->next) 39 { 40 q.push({f.ptr->next->val, f.ptr->next}); 41 } 42 } 43 return head.next; 44 } 45 };