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;
}
};