Merge Two Sorted Lists and Merge k Sorted Lists

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;    }
};
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章