【LeetCode热题100】23. 合并 K 个升序链表(链表)

一.题目要求

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

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

二.题目难度

困难

三.输入样例

示例 1:
输入:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]

解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到一个有序链表中得到。
1->1->2->3->4->4->5->6

示例 2:
输入:lists = []
输出:[]

示例 3:
输入:lists = [[]]
输出:[]

提示:

  • k == lists.length
  • 0 0 0 <= k <= 1 0 4 10^4 104
  • 0 0 0 <= lists[i].length <= 500 500 500
  • − 1 0 4 -10^4 104 <= lists[i][j] <= 1 0 4 10^4 104
  • lists[i] 按 升序 排列
  • lists[i].length 的总和不超过 1 0 4 10^4 104

四.解题思路

解法1:n个指针从n个链表的头开始同时移动,比较并插入最小值,而后指向最小值的指针后移。时间 O ( k 2 n ) O(k^2n) O(k2n) 空间 O ( 1 ) O(1) O(1)
解法2:最小堆
维护当前每个链表没有被合并的元素的最前面一个,k个链表就最多有 k个满足这样条件的元素,每次在这些元素里面选取val属性最小的元素合并。在选取最小元素的时候,用最小堆存这k个满足条件的元素。
解法3:分治法两个两个比较

五.代码实现

解1

/*** 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) {ListNode* dummy = new ListNode(-1);ListNode* sup = dummy;ListNode* tmp;int pMin = INT_MAX;vector<ListNode*>::iterator minIt = lists.begin();bool changed = true;while(changed){   changed = false;for(vector<ListNode*>::iterator it = lists.begin(); it != lists.end();it++){if(*it != nullptr && (*it)->val < pMin){changed = true;minIt = it;pMin = min((*it)->val, pMin);}    }if(changed){tmp = *minIt;*minIt = (*minIt)->next;        sup->next = tmp;tmp = nullptr;sup = sup->next;}pMin = INT_MAX;tmp = nullptr;}return dummy->next;}
};

解2

/*** 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 Compare {
public:bool operator()(const ListNode* l1, const ListNode* l2) const {return l1->val > l2->val;  }
};class Solution {
public:ListNode* mergeKLists(vector<ListNode*>& lists) {ListNode* dummy = new ListNode(-1);ListNode* sup = dummy;priority_queue<ListNode*,vector<ListNode*>,Compare> listQueue;for(auto listnode :lists){if(listnode) listQueue.push(listnode);}while(!listQueue.empty()){ListNode* t = listQueue.top();listQueue.pop();sup->next = t;sup = sup->next;if(t->next) listQueue.push(t->next);}return dummy->next;}
};

六.题目总结

在 C++ 标准模板库(STL)中,std::priority_queue 是一个容器适配器,它提供了对内部容器的有限访问,专门设计用来在固定集合中管理最大(或最小)的元素。priority_queue 通常实现为一个最大堆,其中最大的元素总是位于顶部。然而,它也可以配置为最小堆,这时最小的元素位于顶部。

std::priority_queue 的模板声明如下:

template<class T,class Container = std::vector<T>,class Compare = std::less<typename Container::value_type>
> class priority_queue;

这里有三个模板参数:

  • T - 元素类型。
  • Container - 实际用于存储数据的容器类型,必须是顺序容器,并支持 front(), push_back(),
    pop_back() 操作,比如 std::vector 或 std::deque。
  • Compare - 一个用于元素比较的函数对象的类型。这个比较对象决定了元素的排序方式,从而影响优先队列中元素的优先级。

为什么需要一个类型而不是一个函数实例
当我们谈到模板参数时,特别是指 std::priority_queue 的第三个参数,我们指的是类型而不是特定的函数实例或函数指针。这是因为模板在编译时需要类型信息来生成代码,而不是运行时的函数实例。Compare 需要是一个类型,因为 STL 在编译时实例化容器和算法,而不是在运行时。

你提供的类型应该定义了 operator(),这使得其实例可以像函数一样被调用。因此,你通常会提供一个结构体或类,其中包含重载的 operator() 方法。priority_queue 使用这个类型的实例来比较元素,确定它们在堆中的顺序。

这种设计允许 priority_queue 具有更大的灵活性和泛化能力。通过模板参数化比较函数,可以在不改变容器代码的情况下,定制不同的排序行为。用户可以定义任何满足需求的比较逻辑,只要它遵循正确的接口(即提供 operator())。

示例:使用自定义比较类型
想定义一个最小堆,你可以这样定义比较类型:

struct MinCompare {bool operator()(int lhs, int rhs) const {return lhs > rhs; // 对于最小堆,我们使用大于比较}
};std::priority_queue<int, std::vector<int>, MinCompare> minHeap;

在这个例子中,MinCompare 是一个自定义的比较类型,它定义了 operator() 来实现最小堆的逻辑。priority_queue 使用 MinCompare 实例来比较元素并维持堆的结构。

通过将比较逻辑封装在类型中,priority_queue 能够在编译时获得所有必要的信息来正确地管理元素,同时为用户提供了定制其行为的灵活性。这就是为什么 priority_queue 需要一个比较类型而不是函数实例作为模板参数的原因。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/750382.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在react中使用tailwindcss

安装tailwind css npm i -D tailwindcssnpm:tailwindcss/postcss7-compat postcss^7 autoprefixer^9安装 CRACO 由于 Create React App 不能让您覆盖原生的 PostCSS 配置&#xff0c;所以我们还需要安装 CRACO 才能配置 Tailwind。 npm install craco/craco配置CRACO 在项目根…

【Algorithms 4】算法(第4版)学习笔记 18 - 4.4 最短路径

文章目录 前言参考目录学习笔记0&#xff1a;引入介绍1&#xff1a;APIs1.1&#xff1a;API&#xff1a;加权有向边1.2&#xff1a;Java 实现&#xff1a;加权有向边1.3&#xff1a;API&#xff1a;加权有向图1.4&#xff1a;Java 实现&#xff1a;加权有向图1.5&#xff1a;AP…

android studio设置flutter和dart的sdk配置

提示没有配置dart sdk的时候&#xff0c;其实只需要配置一下flutter的sdk就可以了&#xff0c;因为flutter的安装包里面包含了dart的sdk&#xff1a; 按照提示选中这个flutter的安装包路径就可以了&#xff1a; 并且需要开启windows的开发者开关&#xff1a;start ms-settings:…

Rancher操作手册(v2.7.5-rc1)

1.登录 访问地址&#xff1a;10.66.55.132使用账号和密码登录。初始的页面是英文版本&#xff0c;可以点击左下方改为简体中文 登录成功后可以看到现有的集群。右上角可以进行新集群的创建和导入已有集群。点击箭头所指的蓝色集群名称可以进入集群。 2.集群仪表盘 进入到集…

文字弹性跳动CSS3代码

文字弹性跳动CSS3代码&#xff0c;源码由HTMLCSSJS组成&#xff0c;记事本打开源码文件可以进行内容文字之类的修改&#xff0c;双击html文件可以本地运行效果&#xff0c;也可以上传到服务器里面&#xff0c;重定向这个界面 下载地址 文字弹性跳动CSS3代码

神经网络中激活函数的绘制——阶跃函数、sigmoid函数、ReLU函数

一、阶跃函数 import numpy as np import matplotlib.pylab as plt def step_function(x):return np.array(x>0)x np.arange(-5.0,5.0,0.1) y step_function(x) plt.plot(x, y) plt.ylim(-0.1, 1.1) plt.show() 二、sigmoid函数 import numpy as np import matplotlib.p…

Java多线程学习(一)

多线程学习&#xff08;二&#xff09;&#xff1a;http://t.csdnimg.cn/Q8Koc 目录 1、什么是多线程 2、如何创建多线程&#xff08;多个方法&#xff09; 方法一&#xff1a;继承Thread类创建线程 方法二&#xff1a;实现Runnable接口创建线程 方法三、实现Callable接口…

Day46-http和www基础1

Day46-http和www基础1 1. 用户访问网站基本流程2. DNS系统解析基本流程3. DNS功能4. DNS树形结构介绍5. DNS解析流程&#xff08;核心&#xff09;6. 查看生产【授权DNS】并设置解析7. dig查看实际DNS解析8. 企业要不要搭建DNS服务器&#xff1f;9. HTTP协议10. HTTP协议版本11…

Kubernetes 编排系统

Kubernetes 编排系统 Kubernetes&#xff08;简称K8s&#xff09;是一个开源的容器编排平台&#xff0c;用于自动化部署、扩展和管理容器化应用程序。它提供了一种灵活而强大的方式来管理容器化应用程序的生命周期&#xff0c;包括自动化部署、扩展、负载均衡、故障恢复等功能…

16、技巧之九: 修改参数,如何让表格翻页滚动到底部?【Selenium+Python3网页自动化总结】

1、问题提出 在网页配置参数时&#xff0c;输入参数名称搜索&#xff0c;搜出来的同名参数结果有多个&#xff0c;分布在一个表格的不同行&#xff0c;表格是动态加载的&#xff0c;需要滚动鼠标才能把所出参数找出来。用selenium怎么实现这种参数修改&#xff1f; 2、网页元素…

计算机网络 |内网穿透

其实内网穿透&#xff0c;也挺好玩的&#xff0c;如果在大学的时候&#xff0c;那个时候讲计算机网络的老师能横向延展&#xff0c;估计课也会更有趣不少&#xff0c;本来计算机网络这门课就是计算机课程中可玩性最搞的。 只能说&#xff0c;怪可惜的 回到正题&#xff0c;内网…

知名Web3投资基金a16z合伙人Jane Lippencott确认出席Hack.Summit() 2024区块链开发者大会

在区块链技术的风起云涌和Web3生态的蓬勃发展中&#xff0c;知名a16z Crypto的合伙人Jane Lippencott已确认出席即将于2024年4月9日至10日在香港数码港举行的Hack.Summit() 2024区块链开发者大会。作为亚洲首次举办的Hack.Summit()&#xff0c;此次大会将为全球区块链开发者及业…

【JavaScript知识点】预解析、作用域、数据类型、数组常用方法、字符串常用方法

JS知识点 1.预解析2.作用域&#xff1a;一个变量可以生效的范围,这个变量的使用范围就是作用域3.作用域访问规则4.我们的存储空间分成两种栈和堆5.数据类型分为基本数据类型和复杂数据类型6.冒泡排序和选择排序7.数组常用方法8.字符串常用方法9.json 是一种轻量级的数据交换格式…

计算机网络——物理层(数据交换方式)

计算机网络——数据交换方式 提高数据交换方式的必要性电路交换电路交换原理电路交换的阶段建立阶段通信阶段和连接拆除阶段 电路交换的优缺点报文交换什么是报文报文交换的阶段报文交换的优缺点 分组交换分组交换的阶段分组交换的优缺点 数据交换方式的选择数据报方式数据报方…

使用vue3 开发H5 ,需要注意的部分点

以下内容为使用vue3 开发H5 中碰到的几个点&#xff0c;个人愚见。不定期进行补充。 框架端 1. 安装 vite插件 vitejs/plugin-legacy 。 npm add -D vitejs/plugin-legacy使用&#xff1a; 在vite.config.js 中引入 import legacy from vitejs/plugin-legacy; export defau…

相机拍照与摄影学基础

1.相机拍照 相机可能形状和大小不同&#xff0c;但基本功能相同&#xff0c;包括快门速度、光圈和感光度&#xff0c;这些是摄影的通用概念。即使是一次性相机也是基于这三个理念工作的。不同类型相机在这三个概念上的唯一区别是你可以控制这些功能的程度。这三个参数被称为相…

Redis在缓存方面的应用有哪些?如何避免缓存击穿、缓存雪崩等问题?Redis如何实现分布式锁?有哪些注意事项?

Redis在缓存方面的应用有哪些&#xff1f;如何避免缓存击穿、缓存雪崩等问题&#xff1f; Redis在缓存方面的应用广泛且多样&#xff0c;包括但不限于以下几个方面&#xff1a; 页面缓存&#xff1a;Redis可以将Web页面的内容片段&#xff0c;包括HTML、CSS和图片等静态数据&a…

【ESP32接入国产大模型之MiniMax】

1. MiniMax 讲解视频&#xff1a; ESP32接入语言大模型之MiniMax MM智能助理是一款由MiniMax自研的&#xff0c;没有调用其他产品的接口的大型语言模型。MiniMax是一家中国科技公司&#xff0c;一直致力于进行大模型相关的研究。 随着人工智能技术的不断发展&#xff0c;自然语…

基于opencv的图像处理系统的设计与实现

概要 随着计算机技术的飞速发展&#xff0c;图像技术在各领域的研究和应用日渐深入和广泛。opencv是近年来推出的开源、免费的计算机视觉库,利用其所包含的函数可以很方便地实现数字图像处理。本文旨在对opencv进行一个快速全面简介,通过介绍图像处理的相关函数&#xff0c;使读…

安卓UI面试题 56-60

56. 简述IntentService原理分析 ? HandlerThread其实就是为了我们在 子线程中减少自己创建Looper以及运转Looper而出现的, 那么这次的IntentService其实封装的更巧妙,使用 HandlerThread的时候我们还需要创建Handler对象出来, 但是使用IntentService连Handler对象也不用我们…