Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
這個題的思路還是比較清晰的。兩個鏈表都已經排好序,首先,選擇兩個鏈表中頭結點較小的作爲結果的頭結點。然後,依次比較當前位置的下一個節點,將較小的加入結果鏈表即可。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode *head;
if(l1==NULL && l2==NULL)
return NULL;
if(l2==NULL)
return l1;
if(l1==NULL)
return l2;
if(l1->val>l2->val){
head=l2;
l2=l2->next;
}
else{
head=l1;
l1=l1->next;
}
ListNode *tmp=head;
while(l1 && l2){
if(l1->val>l2->val){
tmp->next=l2;
l2=l2->next;
tmp=tmp->next;
}
else{
tmp->next=l1;
l1=l1->next;
tmp=tmp->next;
}
}
if(l1)
tmp->next=l1;
else
tmp->next=l2;
return head;
}
};
Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.
這個問題就比較複雜了。如果還按上面的方法,找出所有鏈表當前節點的最小值加入結果鏈表,時間複雜度過大。這個問題我們採用分治的方法解決。即把k個鏈表的問題分解處理,直至分爲兩個鏈表的合併,這樣就轉化爲上面的方法了。分治的過程類似歸併排序的過程,每次將鏈表的數目分爲等量的兩份。代碼如下:
/**
* 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) {
if(lists.empty())
return NULL;
return helper(lists,0,lists.size()-1);
}
ListNode* helper(vector<ListNode*>& lists, int l, int r){//分治遞歸
if(l<r){
int m=(l+r)/2;
return merge(helper(lists,l,m),helper(lists,m+1,r));
}
return lists[l];
}
ListNode* merge(ListNode* l1, ListNode* l2){//雙鏈表合併
ListNode *head;
if(l1==NULL && l2==NULL)
return NULL;
if(l2==NULL)
return l1;
if(l1==NULL)
return l2;
if(l1->val>l2->val){
head=l2;
l2=l2->next;
}
else{
head=l1;
l1=l1->next;
}
ListNode *tmp=head;
while(l1 && l2){
if(l1->val>l2->val){
tmp->next=l2;
l2=l2->next;
tmp=tmp->next;
}
else{
tmp->next=l1;
l1=l1->next;
tmp=tmp->next;
}
}
if(l1)
tmp->next=l1;
else
tmp->next=l2;
return head;
}
};
解決這個問題還有一種方法——用堆來解決。取出每個鏈表的當前節點,並構建最小堆。那麼堆頂的節點即爲最小值,可以放入結果鏈表中,然後將該最小值所在鏈表的下一個節點加入堆中,重新構建最小堆。重複這個過程,直到堆爲空。代碼如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
#define LN ListNode*
#define HEAP heap.begin(),heap.end()
#define PB push_back
#define INF 1000000
struct node
{
int val;
LN from;
node(ListNode* n)
{
if ( n==NULL )
{
val=INF;
}
else
{
val=n->val;
}
from=n;
}
bool operator<(const node& other)const
{
return val<other.val;
}
bool operator>(const node& other)const
{
return val>other.val;
}
};
class Solution {
public:
ListNode *mergeKLists(vector<ListNode *> &lists) {
// Start typing your C/C++ solution below
// DO NOT write int main() function
if (lists.empty()) return NULL;
int n= lists.size();
vector<node> heap;
heap.reserve(n);
for( int i=0;i<n;i++)
heap.PB(node(lists[i]));
make_heap(HEAP,greater<node>());
LN head= new ListNode(0);
LN pL = head;
pop_heap(HEAP,greater<node>());
node small=heap.back();
heap.pop_back();
while(small.val!=INF)
{
LN next=small.from->next;
pL->next=small.from;
small.from->next=NULL;
pL=pL->next;
heap.PB(node(next));
push_heap(HEAP,greater<node>());
pop_heap(HEAP,greater<node>());
small=heap.back();
heap.pop_back();
}
LN ret=head->next;
delete head;
return ret; }
};