Leetcode-Merge k Sorted Lists

Leetcode-Merge k Sorted Lists


昨天师兄的同事和他一起回实验室看我们,顺便交流了一下面试的事情。他在猿题库碰到了面试题:merge K sorted arrays。我马上就联想到了Leetcode上的相似的题目,当时做的时候理解的不是很深,现在拿来再反思一下。

这道题目在分布式系统中非常常见,来自不同client的sorted list要在central server上面merge起来1
有两种方法:1.分治法;2.堆。

分治法

最初,我是逐个list合并,像滚雪球一样,有序的list越来越长,直到与最后一个list合并后,所有的list合并成功。提交后超时。设每个list长度为 n ,由于merge的时间复杂度是O(n),所有总的时间复杂度是: n(k1)+n(k2)++n=nk2 。而这与插入排序法的时间复杂度一致。

所以,我们借用归并排序的思想:将问题分解成两个子任务,即分成前后各一半的list,分别将它们排成有序的list之后,再将两个有序的list合并。这样时间复杂度满足: T(k)=T(k/2)+O(nk)T(k)=O(nklogk)

struct ListNode *mergeTwoLists(struct ListNode *l1, struct ListNode *l2)
{
    if (NULL == l1)
        return l2;
    if (NULL == l2)
        return l1;
    struct ListNode *head = NULL;
    if (l1->val < l2->val)
    {
        head = l1;
        head->next = mergeTwoLists(l1->next, l2);
    }
    else
    {
        head = l2;
        head->next = mergeTwoLists(l1, l2->next);
    }
    return head;

}

struct ListNode *mergeLists_sub(struct ListNode *lists[], int begin, int end)
{
    if (begin > end)
        return NULL;
    if (begin == end)
        return lists[begin];
    int mid = (begin + end)/2;
    struct ListNode *left = mergeLists_sub(lists, begin, mid);
    struct ListNode *right = mergeLists_sub(lists, mid+1, end);
    return mergeTwoLists(left, right);
}

struct ListNode *mergeKLists(struct ListNode *lists[], int k) {
    return mergeLists_sub(lists, 0, k-1);
}

堆(优先队列)

基本思路是这样的:
1.取每个list的第一个元素构成一个最小堆(或者说优先队列),
2.重复以下步骤:
a.取出最小堆的第一个元素;(若用优先队列,直接push())
b.用a中取出的元素的所在list的下一个元素替换堆首元素,再重新使堆有序化。如果该list已经是空的话,就用无穷大代替。(若用优先队列,先pop(),如果不为空,再push进a中取出的元素的所在list的下一个元素)
复杂度同分治法。

class nodeComparison
{
    //此函数要加上public。
    //“>”说明是最小堆。“<”说明是最大堆
public: bool operator() (Node* n1, Node* n2)
    {
        return n1->val > n2->val;
    }
};


Node* mergeKsortedLists(vector<Node*> &lists)
{
    if (lists.empty())
        return NULL;
    priority_queue<Node*, vector<Node*>, nodeComparison> pq;

    int sz = lists.size();
    for (int i = 0; i < sz; i++)
    {
        if (lists[i] != NULL)
            pq.push(lists[i]);
    }

    Node helper(0);
    Node *helper_ptr = &helper;

    while (!pq.empty())
    {
        Node *toAdd = pq.top();
        pq.pop();
        helper_ptr->next = toAdd;
        helper_ptr = toAdd;
        if (toAdd->next)
            pq.push(toAdd->next);
    }
    return helper.next;
}

如果链表变成数组,该如何处理呢?这里的做法是把每个元素都变成一个struct node节点,存储该元素所在二维数组的位置以及下一个元素,本质上和sorted lists一样。但是如果是二维vector呢,每一维的长度可能不等,所以还得加上每个一维vector的长度。代码写得很精彩,正好可以复习一下今天写的堆排序的相关代码!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值