原題
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Example:
Input:
[
1->4->5,
1->3->4,
2->6
]
Output: 1->1->2->3->4->4->5->6
思路
拍腦門算法
合併k個有序鏈表,假設每個鏈表中的元素個數最多爲n,那麼總共的元素個數爲kn個,拍腦門算法可以將每個鏈表頭結點值進行k-1次比較,得到最小的元素放到新的鏈表裏,總共比較次數爲kn,時間複雜度爲
歸併排序
一般出現排序的題目,時間複雜度要儘可能降爲或者,而一出現,就要往二叉樹上靠,這裏可以使用分治法來解決這個問題。
對k個有序鏈表進行兩兩排序,然後對排序結果再進行兩兩排序,重複此步驟,直到最後合成一個鏈表。
如上圖,總共有k個鏈表,那麼上面二叉數的層高爲,每層需要比較的元素個數均爲(即所有的元素都要進行一次比較),那麼總的時間複雜度爲
代碼
class Solution {
public:
//假設lists中的(l, m), (m+1, r)區間已經完成合並,並且合併的鏈表頭結點在lists[l],lists[m+1]
//然後合併lists[l],lists[m+1]兩個鏈表,並將頭結點賦予lists[l])(即最左邊的索引)
void merge(vector<ListNode*> &lists, int l, int m, int r) {
ListNode *p = lists[l], *q = lists[m+1];
ListNode *new_list = NULL, *head = NULL;
//判斷兩個鏈表是否爲空
if (q == NULL) return ;
if (p == NULL) {
lists[l] = q;
return ;
}
new_list = new ListNode(-1);
head = new_list;
while (p != NULL && q != NULL)
{
if (q->val < p->val)
{
new_list->next = new ListNode(q->val);
q = q->next;
}
else
{
new_list->next = new ListNode(p->val);
p = p->next;
}
new_list = new_list->next;
}
if(p == NULL)
new_list->next = q;
if(q == NULL)
new_list->next = p;
lists[l] = head->next;
}
//分治法
//將lists分爲(l, m), (m+1, r)兩個部分,分別進行合併,並將合併好的鏈表頭結點賦予lists[l], lists[m+1](即最左邊的索引)
//合併lists(l), lists[m+1]
void divide_conquer(vector<ListNode*> &lists, int l, int r) {
if (l < r) {
int m = (l+r)/2;
divide_conquer(lists, l, m);
divide_conquer(lists, m+1, r);
merge(lists, l, m, r);
}
}
//返回最左邊索引的頭結點
ListNode* mergeKLists(vector<ListNode*>& lists)
{
if (lists.size() == 0)
return NULL;
divide_conquer(lists, 0, lists.size() - 1);
return lists[0];
}
};