Merge k Sorted Lists
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
一開始的思路是先將兩個鏈表合併,然後每次從剩下的鏈表中取出一個鏈表與之合併。假設共有m條鏈表且每條鏈表長度均爲n,則複雜度爲:
2n+3N+4n+5n+6n+……+mn = (m-1)(m+2)n/2
也即複雜度爲O(n*m^2)
經過驗證發現超時了。因此,修改了思路。借鑑堆排序思想,構建一個小頂堆,每次從堆頂中取一個元素構建鏈表,並加入一個新的元素重新建堆。該思路算法複雜度爲O(mn)
代碼如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution
{
public:
//已知heap_array中除了heap_array[s]外均滿足小頂堆的定義
//調整heap_array[s]使heap_array成爲一個小頂堆
void HeapAdjust(vector<ListNode *> & heap_array, int s, int n)
{
ListNode * temp = heap_array[s];
for(int i=2*s; i<=n; i*=2)
{
if(i<n && heap_array[i]->val > heap_array[i+1]->val)
i++;
if(temp->val <= heap_array[i]->val)
break;
heap_array[s] = heap_array[i];
s = i;
}
heap_array[s] = temp;
}
ListNode *mergeKLists(vector<ListNode *> &lists)
{
int num = lists.size();
int length = 0; //lists中非空鏈表數目
int i = 0;
if(!num)
return NULL;
//將非空鏈表置於lists前面
for(i=0; i<num; i++)
{
if(lists[i]!=NULL)
{
if(i != length)
lists[length] = lists[i];
length ++;
}
}
if(!length)
return NULL;
else if(length == 1)
return lists[0];
ListNode * head = new ListNode(0);
ListNode * travel = head;
//構建一個數組,建堆並進行堆排序,堆排序,有效數據下標從1開始
vector <ListNode *> heap_array (length+1);
for(i=1; i<=length; i++)
heap_array[i] = lists[i-1];
//建堆
for(i=length/2; i>0; i--)
HeapAdjust(heap_array,i,length);
//取出最小結點,並更新數組
while(length > 1)
{
travel->next = heap_array[1];
travel = travel->next;
if(heap_array[1]->next != NULL)
heap_array[1] = heap_array[1]->next;
else //如果某一個鏈表已經完全取盡,則將最後一個鏈表換上,並且length-1
{
heap_array[1] = heap_array[length];
heap_array[length] = NULL;
length = length -1;
}
HeapAdjust(heap_array,1,length);
}
travel->next = heap_array[1];
travel = head;
head = head->next;
delete travel;
return head;
}
};