Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
題目分析:
k個排過序的鏈表,要將它們合併起來就要求能夠在較短的時間內將當前的k個數進行排序,並且能夠高效得支持數字的增刪操作。
可以使用的方法有:敗者樹,堆排序,這兩個算法在插入、刪除節點的時候複雜度都爲O(n)。
處理流程:
1. 使用每個鏈表起始的節點,共k個節點,進行堆排序,複雜度
2. 之後從這k個節點中選擇一個最大的,插入到新的鏈表中去。
3. 被選中的那個鏈表的節點的下一個節點如果存在,插入到堆中去。
4. 回到步驟2
結束條件爲堆中元素少於等於1個,即只有最後一個鏈表或沒有鏈表剩餘。
使用堆的代碼:
需要注意的是,priority_queue默認實現的是最大堆,而stl中的比較函數默認是通過“
/**
* 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) {
priority_queue<ListNode *, vector<ListNode *>, cmp> min_heap;
for(int i = 0; i < lists.size(); ++i) {
if(lists[i] != NULL)
min_heap.push(lists[i]);
}
ListNode *pre_head(new ListNode(0)), *curr(pre_head);
while(min_heap.size() > 1) {
curr->next = min_heap.top();
min_heap.pop();
curr = curr->next;
if(curr->next != NULL)
min_heap.push(curr->next);
}
if(min_heap.size() == 1) {
curr->next = min_heap.top();
min_heap.pop();
}
ListNode *head = pre_head->next;
pre_head->next = NULL;
delete pre_head;
return head;
}
};
使用敗者樹的代碼:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
int size = lists.size();
if (size == 0)
return NULL;
int *key = new int[size + 1];
key[size] = INT_MIN;
ListNode **elements = new ListNode*[size];
int *loser = new int[size];
for (int i = 0; i < size; i++) {
elements[i] = lists[i];
loser[i] = size;
if (elements[i] != NULL)
key[i] = elements[i]->val;
else key[i] = INT_MAX;
}
for (int i = 0; i < size; i++) {
adjust(loser, key, i, size);
}
ListNode *head = NULL, *curr = NULL;
while (true) {
if (key[loser[0]] == INT_MAX) {
break;
curr->next = NULL;
}
if (head == NULL) {
head = elements[loser[0]];
curr = elements[loser[0]];
elements[loser[0]] = elements[loser[0]]->next;
}
else {
curr->next = elements[loser[0]];
curr = curr->next;
elements[loser[0]] = elements[loser[0]]->next;
}
if(elements[loser[0]] != NULL)
key[loser[0]] = elements[loser[0]]->val;
else
key[loser[0]] = INT_MAX;
adjust(loser, key, loser[0], size);
}
return head;
}
void adjust(int loser[], int key[], int k, int size) {
for (int i = (size + k)/2; i > 0; i /= 2) {
if (key[loser[i]] < key[k]) {
int temp = k;
k = loser[i];
loser[i] = temp;
}
}
loser[0] = k;
}
};