合併K個已排序的連結串列。返回一個排序連結串列
阿新 • • 發佈:2019-02-01
本題源自LeetCode
-------------------------------------------------------------
思路1 : 優先佇列
1 遍歷所有的連結串列,將首節點放入優先佇列。
2 取出優先佇列的頭,即最小的節點。連結到新連結串列的尾部。
3 如果佇列首節點的連結串列不空,就將下一個節點入佇列。依次迴圈1-3步。
程式碼:
struct compare{ bool operator()(const ListNode* a,const ListNode* b){ return a->val > b->val; } }; public: ListNode *mergeKLists(vector<ListNode *> &lists) { priority_queue<ListNode*,vector<ListNode*>,compare> que; //優先佇列 for(auto node:lists){ if(node) que.push(node); } if(que.empty()) return NULL; ListNode* root=new ListNode(0); root->next=NULL; ListNode* pre=root; while(que.size()){ ListNode* p=que.top(); //取佇列頭部,最小的那個節點 que.pop(); pre->next=p; pre=p; if(pre->next){ //取節點那個連結串列不空,向後遍歷 que.push(pre->next); } } return root->next; }
思路 2 : 最小堆
1 和上面一樣遍歷 各連結串列首節點 然後建堆
2 取出堆頂點,然後調整堆
3 如果當前最小節點的連結串列不空,則下一個節點入堆,調整堆,迴圈
程式碼:
struct compare{ bool operator()(const ListNode* a,const ListNode* b){ return a->val > b->val; } }; public: ListNode *mergeKLists(vector<ListNode *> &lists) { vector<ListNode*> vec; //最小堆 for(auto node:lists){ if(node) vec.push_back(node); } ListNode* root=new ListNode(0); root->next=NULL; ListNode* pre=root; make_heap(vec.begin(),vec.end(),compare()); //建堆 while(vec.size()){ pre->next=vec[0]; pop_heap(vec.begin(),vec.end(),compare()); //將第一個節點與最後一個作交換 vec.pop_back(); //刪除最後一個節點 pre=pre->next; if(pre->next){ vec.push_back(pre->next); push_heap(vec.begin(),vec.end(),compare()); } } return root->next; }
思路3
歸併排序。先兩兩合併然後在合併
程式碼:
ListNode *mergeKLists(vector<ListNode *> &lists) { if(lists.size()==0) return NULL; while(lists.size()>1){ lists.push_back(mergeList(lists[0],lists[1])); lists.erase(lists.begin()); lists.erase(lists.begin()); } return lists.front(); } ListNode* mergeList(ListNode* l1,ListNode* l2){ if(l1==NULL) return l2; if(l2==NULL) return l1; if(l1->val<l2->val){ l1->next=mergeList(l1->next,l2); return l1; }else{ l2->next=mergeList(l1,l2->next); return l2; } }