LeetCode-023. Merge k Sorted Lists

1. 题目

Merge k Sorted Lists

合并k条升序链表

2. 分析

Merge Two Sorted Lists 从2个扩展到k个
1:最直接的思路就是两两合并,1,2先合并,合并好了再跟3/…/k合并
注意

  • ListNode *p = lists[0];而非ListNode *p = &lists[0];
  • i的下标从1开始
  • p = mergeTwoLists(p, lists[i]);函数调用结果要赋给p返回

2:借助归并排序的思路,采用分治法Divide and Conquer Approach
先分成两个子任务,然后递归求子任务,最后回溯回来
简单来说就是不停的对半划分,比如k个链表先划分为合并两个k/2个链表的任务, 再不停的往下划分,直到划分成只有1或2个链表的任务,开始合并
注意

  • left, right的大小要分3种情况讨论
  • mergeLists(lists, mid + 1, right);而非mergeLists(lists, mid, right);不要写错

3:借助数据结构—最小堆
先把k个链表的首元素都放入最小堆中自动排好序
每次取出最小节点插入结果链表
将取出节点的下一节点再放入堆中
重复这个过程,直到最小堆为空
则合并成功,返回首节点即可
注意

  • push进q之前应该判断lists[i] != nullptr
  • tmp = q.top();而非tmp = q.front();
  • if(tmp->next)之后是q.push(tmp->next);而非q.push(tmp);
3. 代码

函数 mergeTwoLists 在Merge Two Sorted Lists中任选一种复用均可
1)

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int len = lists.size();

        if(len == 0)
            return NULL;

        ListNode *cur = lists[0];
        for(int i = 1; i < len; ++i)
        {
            cur = mergeTwoLists(cur, lists[i]);
        }

        return cur;
    }

    ListNode* mergeTwoLists(ListNode *l1, ListNode *l2) {
        // 复用mergeTwoLists
    }

};

2)

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int len = lists.size();

        if(len == 0)
            return NULL;

        return mergeKListsRecursive(lists, 0, len - 1);
    }

    ListNode* mergeKListsRecursive(vector<ListNode*>& lists, int left, int right)
    {
        if(left == right)
            return lists[left];
        else if(left < right)
        {
            int mid = left + (right - left) / 2;
            ListNode *l = mergeKListsRecursive(lists, left, mid);
            ListNode *r = mergeKListsRecursive(lists, mid + 1, right);
            return mergeTwoLists(l, r);
        }
        else
            return NULL;
    }


    ListNode* mergeTwoLists(ListNode *l1, ListNode *l2) {
        // 复用mergeTwoLists
    }

};

3)

// 不要遗漏 operator 后面的 () 以及 struct 最后的;
struct cmp
{
    bool operator()(ListNode *a, ListNode *b)
    {
        return a->val > b->val;
    }
};

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        int len = lists.size();
        if(len <= 0)
            return NULL;

        priority_queue<ListNode*, vector<ListNode*>, cmp>  q;
        // 注意一定要判断 lists[i] != NULL
        // 否则后面会出错的
        for(int i = 0; i < len; ++i)
        {
            if(lists[i] != NULL)
            {
                q.push(lists[i]);
            }

        }

        ListNode *head = NULL;
        ListNode *prev = NULL;
        ListNode *temp = NULL;

        while(!q.empty())
        {
            temp = q.top();
            q.pop();

            if(prev == NULL)
                head = temp;
            else
                prev->next = temp;

            // prev可能为 NULL 所以不能写 prev = prev->next;
            prev = temp;
            // push前一定要判断 lists[i] != NULL
            if(temp->next != NULL)
                q.push(temp->next);
        }

        return head;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值