leetcode-23 合并K个升序链表

在这里插入图片描述

与之前的题目类似:
leetcode-21 合并两个有序链表

这是一个多条有序链表,然后不断去选择查询,然后定义一个新的节点,把链表接入进去,唯一刚开始觉得不好做的情况是,多条链表不好操作,判断大小也麻烦。

之前写:two sum,three sum,four sum这一种题目的时候,我很希望能找一个通法去解决,但是就找不到。

这题的思路我能想到,但是边界一直处理不了。

题目分析如下:
(1)和合并两条有序链表的方式一样,找到头结点的每一个最小是,之后寻找下一个头节点。
(2)那么如何去找一个序列中的最小值呢?当然是优先队列,其实就是堆,请参考《算法笔记》335页,这里需要去定义一个小根堆,通常我们定义的方式是这样的:

这里参入一个连接介绍一下小根堆的写法:STL-priority_queue用法(重点: 升序,小根堆)

priority_queue<int,vector<int>,greater<int>>

顺便提一下:定义大根堆的方法:

priority_queue<int,vector<int>,less<int>>

堆的查找是O(1)复杂度,但是插入的一个数是O(log n)的负载度,如果这里和循环对比,可能好多了。

(3)之后就是多路归并的情况了,如果找到值,插入链表之后,就要把当前节点的最后一个值送到堆里面,之后小根堆会管这件事。

代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        这很像是多路归并排序的感觉,但是需要去使用链式去表达出来
        struct cmp{
            bool operator() (ListNode* a,ListNode* b){
                return a->val>b->val;
            }
        };

        //定义一个大顶堆
        priority_queue<ListNode*,vector<ListNode*>,cmp> heap;
        auto dummy=new ListNode(-1),tail=dummy;
        //如果存在k个序列,然后k个序列去排序连接,同样是可以得到答案
        //前k个点取出最小值,方式有很多,优先队列可以。
        //优先队列是大根堆,虽然可以去使用greater去使用
        
        //现在的操作是,先把k个链表的头节点插入堆里面去。然后选出一个最小的数
        //如果是非空,才可以去进行插入
        for(auto nums:lists) if(nums) heap.push(nums);

        //然后就开始去进行k路归并,在堆里面找出最小的值
        //当堆里面存在元素,取出头结点的元素,然后插入当tail的尾部后面
        while(heap.size()){
            auto t=heap.top();
            heap.pop();

            tail=tail->next=t;//插入完成之后,t成为了新的为节点,还是需要去跟新一下

            //如果下一个节点存在元素的话,那么将t的下一个节点插入,其实堆就是维护了一段长度的列队

            if(t->next) heap.push(t->next);
        }
        //如果存在最后一条链表,然后再去插入一下
        return dummy->next;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值