Problem :
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
Algorithm:
本题为一个多路归并的问题,即将多个有序数组或链表(统称为序列)合并成为一个有序的序列。
回想归并排序中二路归并时我们的做法。我们从两个序列的头部元素开始比较(即当前下标为0),将较小者加入一个新的序列中,同时拥有较小元素序列的当前下标加1。每次比较的复杂度为O(1),总体复杂度为O(n)。
对于k路归并,我们同样可采用上述方法,即遍历所有序列,找出最小元素加入新序列,同时相应下标加1。该时间复杂度为O(kn)。
然而,该算法可以进行优化。因为查找最小元素的过程我们可以通过建堆来处理。这样,我们只需要用O(logk)的时间即可找到最小元素,因此,总时间复杂度可优化为O(nlogk)。
Code:
#include<iostream>
#include<functional>
#include<queue>
using namespace std;
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
struct cmp{
bool operator ()(ListNode* n1, ListNode* n2){
return n1 -> val > n2 -> val; //最小值优先
}
};
class Solution {
public:
ListNode* mergeKLists(vector<ListNode*>& lists) {
ListNode* head = new ListNode(0); //建表头
ListNode* tp = head;
priority_queue<ListNode*, vector<ListNode*>, cmp > que;
//使非空链表表头元素进队
for(int i = 0; i < lists.size(); ++ i) {
if(lists[i])
que.push(lists[i]);
}
while(que.size()) {
ListNode* temp = que.top();
que.pop();
//将表头结点加入答案链表
tp -> next = temp;
tp = tp -> next;
//当前链表非空,则将下一结点推入队列
if(temp -> next) que.push(temp -> next);
}
tp = head -> next; //删表头
delete head;
return tp;
}
};