Leetcode23. 合并K个升序链表 -两种方法

news/2024/5/17 18:13:35 标签: 链表, 数据结构, , 归并排序, c++

合并k个升序<a class=链表" />

23. 合并K个升序链表

    • 食用指南:
    • 题目描述:
    • 题目分析:
    • 算法模板:
    • 代码实现:
      • 法一:漏斗
      • 法1.5:迭代器 / 范围for不需要判断输入为空
      • 法二:两两合并链表
    • 注意点:
      • 1. 自定义STL中的
      • 2. 被空值卡输入:

食用指南:

Leetcode专栏开启了,由于博主闭关期末,所以每日只能一题
尽量做到一题多解,先说思路,之后代码实现,会添加必要注释
语法或STL内容会在注意点中点出,新手友好
欢迎关注博主神机百炼专栏,内涵算法基础详细讲解和代码模板

题目描述:

  • 给你一个链表数组,每个链表都已经按升序排列,

    请你将所有链表合并到一个升序链表中,返回合并后的链表

  • 代码背景

class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {

    }
};
  • 题目来源:https://leetcode.cn/problems/merge-k-sorted-lists/

题目分析:

  • 法一:漏斗

    建立一个大小为k的,开始将各个链表头节点加入

    每次将中值最小的节点加入最终的主链表中,同时将该节点的下一个节点入

    内每次push() pop()的时间复杂度都是O(log(k))

    共n个节点,每个节点先push()入,最终pop()出,总时间复杂度为O(2·n·log(k))
    漏斗<a class=堆" />

  • 法二:两两合并链表

    每次遍历两条链表,将其合并,返回头节点作为最终主链表的头节点,

    一共两两合并k-1次,每次主链表长度逐步增加,每次两两合并耗时是上一次加上一条链表长度
    假设每条链表最长n个节点,总时间复杂度为(n + 2n + …… + kn) = O(k2·n)

算法模板:

代码实现:

法一:漏斗

class Solution {
public:
    struct cmp{
        bool operator()(ListNode* p, ListNode* q){
            return p->val > q->val;                 //升序链表,小根,用>号
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.size() == 0) return nullptr;
        ListNode* dummy = new ListNode();
        ListNode* p = dummy;
        priority_queue<ListNode*, vector<ListNode*>, cmp> heap;
        for(int i=0; i<lists.size(); i++){
            if(lists[i])
                heap.push(lists[i]);
        }
        while(!heap.empty()){
            ListNode* tmp = heap.top();
            p->next = tmp;
            p = p->next;
            heap.pop();
            if(tmp->next)
                heap.push(tmp->next);
        }
        p->next = nullptr;
        return dummy->next;
    }
};

法1.5:迭代器 / 范围for不需要判断输入为空

class Solution {
public:
    struct cmp{
        bool operator()(ListNode* p, ListNode* q){
            return p->val > q->val;                 //升序链表,小根,用>号
        }
    };
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* dummy = new ListNode();
        ListNode* p = dummy;
        priority_queue<ListNode*, vector<ListNode*>, cmp> heap;
        for(auto q : lists){
            if(q) heap.push(q);
        }
        while(!heap.empty()){
            ListNode* tmp = heap.top();
            heap.pop();
            p = p->next = tmp;
            if(tmp->next)
                heap.push(tmp->next);
        }
        p->next = nullptr;
        return dummy->next;
    }
};

法二:两两合并链表

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* p, ListNode* q){
        ListNode* dummy = new ListNode();
        ListNode* i = p, *j = q, *k = dummy;
        while(i && j){
            if(i->val < j->val) {
                k = k->next = i;
                i = i->next;
            }else{
                k = k->next = j;
                j = j->next;
            }
        }
        while(i){
            k = k->next = i;
            i = i->next;
        }
        while(j){
            k = k->next = j;
            j = j->next;
        }
        k->next = nullptr;
        return dummy->next;
    }
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        ListNode* head = nullptr;
        for(int i=0; i<lists.size(); i++){
            if(lists[i]){
                head = mergeTwoLists(head, lists[i]);
            }
        }
        return head;
    }
};

注意点:

1. 自定义STL中的

priority_queue<元素类型> A;   //默认大根
priority_queue<元素类型, vector<元素类型>, less<元素类型>>B;    //大根
priority_queue<元素类型, vector<元素类型>, greater<元素类型> > C;    //小根
  • 仿函数类自定义比较函数:

    由于指针直接比较大小,其实是比较地址高低,所以自定义比较函数尤其对于指针适用

struct cmp1{
	bool operator()(ListNode* p, ListNode* q){
		return p->val > q->val;				//大于为小根
		//return p->val < q->val;			//小于为大根
	}
};
//如果ListNode类本身重载过< >运算符号,则直接解引用即可
struct cmp2{
	bool operator()(ListNode* p, ListNode* q){
		return *p > *q;				//大于为小根
		//return *p < *q;			//小于为大根
	}
};
priority_queue<ListNode*, vector<ListNode*>, cmp1> heap1;
priority_queue<ListNode*, vector<ListNode*>, cmp2> heap2;

2. 被空值卡输入:

  • 输入空值情况1:vector<>中没有元素
  • 对策:上手先判空
//输入:[]
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.size() == 0) return nullptr;
    }
};
  • 输入空值情况2:vector<>中含有空元素
  • 对策:向中插入元素前先审查元素是不是nullptr
//输入:[[]]
class Solution {
public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        if(lists.size() == 0) return nullptr;
        priority_queue<ListNode*, vector<ListNode*>, cmp> heap;
        for(int i=0; i<lists.size(); i++){
            if(lists[i])
                heap.push(lists[i]);
        }
    }
};

http://www.niftyadmin.cn/n/426.html

相关文章

达梦数据库逻辑导出工具dexp使用

工具介绍 逻辑导出和逻辑导入数据库对象分为四种级别&#xff1a;数据库级、用户级、模式级和表级。四种级别独立互斥&#xff0c;不能同时存在。 四种级别所提供的功能&#xff1a;  数据库级&#xff08;FULL&#xff09;&#xff1a;导出或导入整个数据库中的所有对象。  …

红黑树原理及旋转

红黑树&#xff0c;本质上来说就是一棵二叉查找树 但它在二叉查找树的基础上增加了着色和相关的性质使得红黑树相对平衡 保证了红黑树的查找、插入、删除的时间复杂度最坏为O(log n) 但它是如何保证一棵n个结点的红黑树的高度始终保持在h logn的呢&#xff1f;这就引出了红黑…

牛客前端刷题(九)—— 打包篇

还在担心面试不通过吗&#xff1f;给大家推荐一个超级好用的刷面试题神器&#xff1a;牛客网&#xff0c;里面涵盖了各个领域的面试题库&#xff0c;还有大厂真题哦&#xff01; 赶快悄悄的努力起来吧&#xff0c;不苒在这里衷心祝愿各位大佬都能顺利通过面试。 面试专栏分享&a…

程序员必知必会的ServiceMesh技术,不会在未来就等着被淘汰吧

Service Mesh技术 服务啮合&#xff08;Service Mesh&#xff09;是一种为了保证“从服务到服务”的安全、快速和可靠的通信而产生的基础架构层。 在云原生架构下&#xff0c;服务啮合层的提出&#xff0c;可以帮助开发者将服务的交互通信问题与微服务内部的业务问题隔离开来…

SARScape中用sentinel-1数据做SBAS-InSAR完整流程(1/2)

SARScape中用sentinel-1数据做SBAS-InSAR完整流程1 SABA-InSAR原理简述2 数据采集和预设2.1 SAR数据采集2.2 DEM数据下载与放置2.3 精密轨道数据下载与放置2.4 制作研究区范围矢量2.5 SARscape Preferences预设3 SAR数据预处理3.1 导入数据3.2 optional files设置3.3 参数设置4…

数据迁移工具 -- Sqoop 安装配置

1、Sqoop概述 Sqoop是一款开源的工具&#xff0c;主要用于在Hadoop(Hive)与传统的数据库&#xff08;mysql、postgresql等&#xff09;间进行数据的传递。可以将关系型数据库&#xff08;MySQL ,Oracle,Postgres等&#xff09;中的数据导入到HDFS中&#xff0c;也可以将HDFS的数…

【Git】Git使用的三个场景总结 | 远程仓库到本地 | 本地获取git仓库 | 远程仓库与本地相连接

&#x1f4ad;&#x1f4ad; ✨&#xff1a; git使用的三个场景总结 | 远程仓库到本地 | 本地获取git仓库 | 远程仓库与本地相连接   &#x1f49f;&#xff1a;东非不开森的主页   &#x1f49c;&#xff1a;学习的过程就是不断接触错误&#xff0c;不断提升自己&#xff0c…

(46)STM32——FATFS文件系统实验

目录 学习目标 运行结果 文件系统 常用系统 FATFS 特点 结构图 移植步骤 disk_initialize disk_status disk_read disk_write disk_ioctl get_fattime 代码 总结 学习目标 我们要来介绍的是FATFS文件系统&#xff0c;这是一个为嵌入式设计的文件系统&#xff0c…