合并k个升序链表

文章介绍了如何使用小根堆合并k个已排序的链表,将它们整合成一个有序链表。通过比较每个链表头节点的值,将最小值的节点添加到结果链表中,堆的使用使得操作效率提升,时间复杂度为O(nlogk),空间复杂度为O(k)。同时,文章还提及了合并两个升序链表的简单方法作为对比。
摘要由CSDN通过智能技术生成
题目描述:
给定k个升序排列的链表,将其合并为一个升序链表并返回头节点。
样例:
Input: lists = [[1,4,5],[1,3,4],[2,6]]
Output: [1,1,2,3,4,4,5,6]
Explanation: The linked-lists are:
[
  1->4->5,
  1->3->4,
  2->6
]
merging them into one sorted list:
1->1->2->3->4->4->5->6
算法思路:

类似于 leetcode21 合并两个升序链表。 仍然是比较各个链表头节点的值,将值最小的节点放在合并后的链表后面。

为了更快的找到k个头节点中值最小的那个节点,可以使用小根堆来保存k个头节点,每次取出堆顶元素插入合并后的链表中,然后将下一个节点加入堆中。

时间复杂度:

由于使用堆维护链表最小值的节点,堆的插入是O(logk)的,所以总的时间复杂度是O(nlogk)。

空间复杂度:

使用了堆所以空间复杂度为O(n)

代码实现:
class Solution {
public:

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

    ListNode* mergeKLists(vector<ListNode*>& lists) {
        priority_queue<ListNode*,vector<ListNode*>,cmp> heap;
        auto dummy = new ListNode(-1), tail = dummy;

        for(auto l:lists){
            if(l)   heap.push(l);
        }

        while(heap.size()){
            auto p = heap.top();
            heap.pop();
            tail = tail->next = p;
            if(p->next) heap.push(p->next);
        }

        return dummy->next;
    }
};

其中,实现小根堆的方法是重载 < 号。

leetcode 21 合并两个升序链表
题目描述:
给定两个升序链表,要求合并这两个链表并返回合并后链表的头节点。
样例:
Input: list1 = [1,2,4], list2 = [1,3,4]
Output: [1,1,2,3,4,4]
算法思路:

使用两个链表的头节点,比较两个节点值的大小,将值小的先插入合并后的链表中,由于链表的头节点会被改变,所以使用虚拟头节点简化代码。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码实现:
class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        auto dummy = new ListNode(-1), tail = dummy;
        while(l1 && l2){
            if(l1->val <= l2->val){
                tail = tail->next = l1;
                l1 = l1->next;
            }
            else{
                tail = tail->next = l2;
                l2 = l2->next;
            }
        }
        if(l1)  tail->next = l1;
        if(l2)  tail->next = l2;
        return dummy->next;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值