Merge Two Sorted Lists and Merge k Sorted Lists

来源:互联网 发布:mac 切换大小写设置 编辑:程序博客网 时间:2024/06/11 10:51
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 1000000struct 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;    }};
0 0
原创粉丝点击