每日算法之二十一:Merge k Sorted Lists

Merge k sorted linked lists and return it as one sorted list. Analyze and describe its complexity.

函数原型如下:

ListNode *mergeKLists(vector<ListNode *> &lists) 

给定一个向量(vector),存储的是每个链表的头指针。要求是把这k个有序链表合并成一个有序的链表输出。

我们可以采用分治法进行处理,分治法在算法结构上要求是能递归的。算法一次或者多次调用自身以解决紧密相关的子问题。

分支法就是将原问题分解为几个规模较小但类似于原问题的子问题,递归的求解这些子问题即可。然后再合并这些子问题的解合并出原问题的解。

分治模式在每层中递归时都有三个步骤,

分解:将原问题分解为子问题。分解n个待排序的链表成各有n/2个链表的子问题。

解决:解决子问题,递归的求解子问题,当然若子问题足够小(只有两个链表)就直接求解。使用递归,一次处理这两个子链表组。

合并:合并子问题的解为原问题的解。将两个链表合为一个链表,循环往复。

代码如下:

<span style="font-size:18px;">/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *mergeTwoList(ListNode *l1,ListNode *l2)
    {//合并两个有序的链表,是在原空间上进行的指针操作,复杂度为O(n)
        ListNode *helper = new ListNode(0);
        ListNode *pre = helper;
        helper->next = l1;//让要返回的链表直接连接到l1上,如果l1->val较小,则插入到l1前面
        while(l1!=NULL && l2!=NULL)
        {
            if(l1->val>l2->val)
            {
                ListNode * p = l2;
                l2 = l2->next;
                p->next = pre->next;
                pre->next = p;
            }
            else 
                l1 = l1->next;
            pre = pre->next;
        }
        if(l2!=NULL)//把最后剩下的l2全部链接到l1后面
            pre->next = l2;
        return helper->next;
    }
    ListNode *helper(vector<ListNode*> lists,int l,int h)
    {
        if(l<h)
        {
            int m = (l+h)/2;
            return mergeTwoList(helper(lists,l,m),helper(lists,m+1,h));//合并子问题的解
        }
        return lists[l];
    }
    ListNode *mergeKLists(vector<ListNode *> &lists) {

        if(lists.size() == 0) 
            return NULL;
        return helper(lists,0,lists.size()-1);//求解子问题
    }
};</span>

下面给出使用堆排序方式的合并方法。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */

struct cmp {
    bool operator() (ListNode *a, ListNode *b) {
        return a->val > b->val;
    }
};

class Solution {
public:
    ListNode *mergeKLists(vector<ListNode *> &lists) {
        // Start typing your C/C++ solution below
        // DO NOT write int main() function
        priority_queue<ListNode *, vector<ListNode *>, cmp> queue;
        for (int i = 0; i < lists.size(); i++) {
            if (lists[i] != NULL) {
                queue.push(lists[i]);
            }
        }
        
        ListNode *head = NULL, *prev = NULL, *temp;
        while (!queue.empty()) {
            temp = queue.top();
            queue.pop();
            if (prev == NULL) {
                head = temp;
            }
            else {
                prev->next = temp;
            }
            prev = temp;
            
            if (temp->next != NULL) {
                queue.push(temp->next);
            }
        }
        
        return head;
    }
};



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值