Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
合併k個排序列表
解題思路是:
取出 k個元素進行堆排序,每次取出最小的元素,插入連結串列中即可
注意本題利用了c++得優先權佇列,優先權佇列底層是用堆實現的
注意本題中一個特殊的測試用例是[{}]
注意vector為空時表示為[],而不是[{}],而後者是大小為1的vector,其中元素是空指標
放入優先權佇列時進行判斷是否為空
放入優先權佇列的元素是ListNode *, 而不是int,主要是保持原有連結串列的地址,避免地址失效,而且放入int話,之後又重新new ListNode(int)開銷還是比較大的.
對放入優先權佇列中得ListNode*要定義一個比較函式物件,如果不定義的話,比較的是地址大小
class Solution { public: struct cmp{ bool operator()(const ListNode* a, const ListNode* b) const{ return a->val > b->val; } }; ListNode *mergeKLists(vector<ListNode *> &lists) { if(lists.empty()) return NULL; priority_queue<ListNode*,vector<ListNode*>,cmp> pq; ListNode *head = new ListNode(0), *pre = head; for(int i = 0 ; i < lists.size(); ++ i){ if(lists[i]) pq.push(lists[i]); } while(!pq.empty()){ ListNode* node = pq.top(); pq.pop(); if(node->next) pq.push(node->next); pre->next = node; pre = node; } pre->next = NULL; return head->next; } };
第二種方法是二分的方法,每次取兩個ListNode * 進行合併
程式中運用了佇列,每次從佇列中取出兩個元素然後合併,將合併後的元素又放入佇列,直到佇列只剩小一個元素為止即可
class Solution { public: ListNode *mergeLists(ListNode* p,ListNode* q){ ListNode* head = new ListNode(0),*pre = head; while(p && q){ if(p->val < q ->val){ ListNode *tmp = p->next; p->next = pre->next; pre->next = p; pre = p; p = tmp; }else{ ListNode *tmp = q->next; q->next = pre->next; pre->next = q; pre = q; q = tmp; } } pre->next = NULL; if(p) pre->next = p; if(q) pre->next = q; return head->next; } ListNode *mergeKLists(vector<ListNode *> &lists) { if(lists.empty()) return NULL; queue<ListNode *> que; for(int i = 0 ; i < lists.size(); ++ i){ if(lists[i]) que.push(lists[i]); } while(que.size()>1){ ListNode* p = que.front();que.pop(); ListNode* q = que.front();que.pop(); que.push(mergeLists(p,q)); } return que.front(); } };