LeetCode Merge K Sorted Lists 問題和解答程式 C++ priority queue實現方法
阿新 • • 發佈:2018-12-29
Merge k Sorted Lists
Mergeksorted linked lists and return it as one sorted list. Analyze and describe its complexity.
其實這個問題真沒有什麼“技巧”;想多了反而不好。不外乎就兩種方法吧:
1. 各列數量頭一個數組成一個數組,然後取其最大者,插入新的陣列。
2. 反覆呼叫兩個數組合並的函式k-1次
下面是第一種方法,用了STL容器priority_queue來實現。當然還有很多其他方法實現。要使用這個容器的技巧就是:增加一個adaptNode相當於一個adaptor,使得可以使用priority_queue,否則因為原來的ListNode沒有< >的操作而無法使用這個容器的。
#include<iostream> #include<vector> #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) {} }; //For adding operator < and >; So that we can form priority_queue struct AdaptNode{ int val; ListNode *cur; AdaptNode(ListNode *node):cur(node) { if(node == NULL) val = INT_MAX; else { val = node->val; } } bool operator<(const AdaptNode& an)const { return val<an.val; } bool operator>(const AdaptNode& an)const { return val>an.val; } }; class Solution { public: ListNode *mergeKLists(vector<ListNode *> &lists) { if (lists.empty()) return NULL; priority_queue<AdaptNode, vector<AdaptNode>, greater<AdaptNode> > pq(lists.begin(),lists.end()); ListNode head(0); ListNode *cura, *small; cura = &head; small = pq.top().cur; while (pq.top().val != INT_MAX) { cura->next = small; cura=cura->next; pq.pop(); pq.push(AdaptNode(small->next)); small = pq.top().cur; } return head.next; } }; int main() try { { ListNode head(0); ListNode fir(1); ListNode sec(2); ListNode thi(3); ListNode fou(4); ListNode fiv(5); ListNode six(6); ListNode sev(7); ListNode eig(8); ListNode nin(9); ListNode ten(10); ListNode da(6); ListNode db(9); ListNode dc(10); ListNode de(19); ListNode df(100); ListNode *pHead1; ListNode *pHead2; ListNode *pHead3; pHead1 = &head; pHead2 = &six; pHead3 = &da; da.next = &db; db.next = &dc; dc.next = &de; de.next = &df; head.next = &fir; fir.next = &sec; sec.next = &thi; thi.next = &fou; fou.next = &fiv; fiv.next = NULL; six.next = &sev; sev.next = &eig; eig.next = &nin; nin.next = &ten; ten.next = NULL; vector<ListNode *>lists; lists.push_back(pHead1); lists.push_back(pHead2); lists.push_back(pHead3); ListNode *pn(NULL); Solution solu; pn = solu.mergeKLists(lists); for(; pn!=NULL; ) { cout<<pn->val<<" "; pn=pn->next; } cout<<endl; return 0; } } catch(out_of_range) { cerr<<"range error\n"; } catch(...) { cerr<<"unknow exception thrown\n"; }
總結:
指標操作真是灰常煩。要格外小心!!!
12.13update 更新方法2程式:
注意:ListNode *head;代表沒有初始化,而ListNode *head = nullptr;代表已經初始化為nullptr空指標了。
ListNode *mergeKLists2(vector<ListNode *> &lists) { if(lists.empty()) return nullptr; ListNode *head = lists[0]; for (int i = 1; i < lists.size(); i++) { head = mergeTwo(head, lists[i]); } return head; } ListNode *mergeTwo(ListNode *n1, ListNode *n2) { if (!n1) return n2; if (!n2) return n1; ListNode *t = n1; if (n1->val > n2->val) { t = n2->next; n2->next = n1; n1 = n2; n2 = t; t = n1; } while (t->next && n2) { if (t->next->val > n2->val) { ListNode *temp = t->next; t->next = n2; n2 = n2->next; t = t->next; t->next = temp; } else t = t->next; } if (n2) t->next = n2; return n1; }
到了現在這種題居然變得這麼簡單了,實現第二種方法感覺就像勢如破竹,一下子通過了。
這種經典的合併程式,基本上可以一口氣寫出來了,還可以任意變換。以前是不敢想象。
不過這個跟某些網上的所謂達到盲打有點不一樣。
我覺得這樣的水平不是死背出來的,而是通過做題,然後熟悉基本方法和操作達到的。
2014-1-25
更新個更加簡潔點的程式。時間複雜度應該是O(n1+n2+n3...)n1,n2,n3...是lists.size()中各個連結串列的長度。空間複雜度是O(1)
ListNode *mergeKLists(vector<ListNode *> &lists)
{
if (lists.empty()) return NULL;
ListNode dummy(0);
dummy.next = lists[0];
for (int i = 1; i < lists.size(); i++)
{
ListNode *p = &dummy;
ListNode *t = lists[i];
while (t && p->next)
{
if (t->val < p->next->val)
{
ListNode *tmp = t->next;
t->next = p->next;
p->next = t;
p = t;
t = tmp;
}
else p = p->next;
}
if (t) p->next = t;
}
return dummy.next;
}