OJ题-合并K个已排序的链表

描述

合并 k 个升序的链表并将结果作为一个升序的链表返回其头节点。

数据范围:节点总数 0≤n≤50000≤n≤5000,每个节点的val满足 ∣val∣<=1000∣val∣<=1000

要求:时间复杂度 O(nlogn)O(nlogn)

下面给出C++代码的两种方法:

方法1:使用优先队列(最小堆)

优先队列可以很方便地处理多个链表头节点的最小值,每次从 K 个链表中取出最小的节点,合并到结果链表中。

思路:

  1. 使用优先队列(最小堆)来存储每个链表的当前头节点。
  2. 每次从堆中取出最小值节点,并将它的下一个节点重新加入堆。

重复这个过程,直到所有链表都被合并。

#include <queue>
#include <vector>
#include <iostream>

struct ListNode {
    int val;
    ListNode* next;
    ListNode(int x) : val(x), next(nullptr) {}
};

// 比较器,用于优先队列
struct Compare {
    bool operator()(ListNode* a, ListNode* b) {
        return a->val > b->val;
    }
};

class Solution {
public:
    ListNode* mergeKLists(std::vector<ListNode*>& lists) {
        // 使用优先队列(最小堆)
        std::priority_queue<ListNode*, std::vector<ListNode*>, Compare> minHeap;
        
        // 初始化:将每个链表的头节点加入优先队列
        for (auto node : lists) {
            if (node) {
                minHeap.push(node);
            }
        }
        
        // 哑节点,便于构建新链表
        ListNode* dummy = new ListNode(0);
        ListNode* cur = dummy;
        
        // 逐步从最小堆中取出最小的节点,并更新链表
        while (!minHeap.empty()) {
            // 取出最小值节点
            ListNode* minNode = minHeap.top();
            minHeap.pop();
            
            // 将最小节点接到新链表的末尾
            cur->next = minNode;
            cur = cur->next;
            
            // 如果最小节点的下一个节点不为空,将其加入堆中
            if (minNode->next) {
                minHeap.push(minNode->next);
            }
        }
        
        // 返回合并后的链表
        return dummy->next;
    }
};

分析:

1、优先队列的使用

  • 优先队列使用自定义比较器 Compare,使得最小的节点始终位于堆顶。
  • 每次从堆顶取出最小的节点,并将它的 next 节点放入堆中。

2、时间复杂度O(N log K),其中 N 是所有链表节点的总数,K 是链表的个数。每次从优先队列取出最小元素的时间复杂度为 O(log K),一共需要执行 N 次。

3、空间复杂度O(K),优先队列最多存储 K 个元素。

方法2:分治法

可以使用分治法逐步将 K 个链表两两合并,类似于归并排序的过程。每次两两合并直到只剩一个链表。

思路:

  1. K 个链表分成两部分,分别合并。
  2. 不断递归分治,直到只剩下两个链表,将它们合并。
  3. 最终得到合并后的链表。
    class Solution {
    public:
        // 合并两个有序链表
        ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
            if (!l1) return l2;
            if (!l2) return l1;
            
            if (l1->val < l2->val) {
                l1->next = mergeTwoLists(l1->next, l2);
                return l1;
            } else {
                l2->next = mergeTwoLists(l1, l2->next);
                return l2;
            }
        }
        
        // 分治法合并 K 个链表
        ListNode* mergeKLists(std::vector<ListNode*>& lists) {
            if (lists.empty()) return nullptr;
            return mergeKListsHelper(lists, 0, lists.size() - 1);
        }
        
        // 分治递归函数
        ListNode* mergeKListsHelper(std::vector<ListNode*>& lists, int left, int right) {
            if (left == right) return lists[left];
            int mid = left + (right - left) / 2;
            ListNode* l1 = mergeKListsHelper(lists, left, mid);
            ListNode* l2 = mergeKListsHelper(lists, mid + 1, right);
            return mergeTwoLists(l1, l2);
        }
    };
    

    分析:

1、分治递归

  • 使用递归将链表划分为两部分,每次递归调用 mergeKListsHelper 合并两部分链表,直到只剩下两个链表。
  • 通过 mergeTwoLists 函数合并两个链表。

2、时间复杂度O(N log K),其中 N 是所有节点的总数,K 是链表的个数。分治法的递归树的高度为 log K,每次合并的时间复杂度为 O(N)

3、空间复杂度O(log K),由于递归调用栈的深度为 log K

总结:

优先队列法适合需要立即获取最小节点的情况,效率较高。

分治法适合逐步合并的方式,利用了归并排序的思想,递归实现较为直观。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Linux s3c2440 开发板上的操作系统实现 ubuntu

使用s3c2440开发板 使用ubuntu 1.ubuntu中的tftp&#xff0c;和nfs Trivial File Transfer Protocol,简单文件 传输协议。 通过网络在客户端与服务器之间进行简单文件 传输。提供不复杂、开销不大的文件传输服务。 Network File System&#xff0c;网络文件系统。通过 网络…

JavaSE - 面向对象编程01

01 什么是面向对象编程(oop) 答&#xff1a;就是只关心对象之间的交互&#xff0c;而并不关心任务是怎样具体完成的。例如把一个大象放进冰箱需要几步&#xff1f;如果是面向对象编程只会思考冰箱和大象之间的交互&#xff0c;那么给出的答案就是&#xff1a;把冰箱门打开&…

Radware 报告 Web DDoS 攻击活动

新一代 HTTPS 洪水攻击的频率和强度急剧增加&#xff0c;攻击者引入的复杂程度也在迅速提高。2024 年上半年&#xff0c;Web 分布式拒绝服务 (DDoS) 攻击的频率和强度显著增加。其中很大一部分活动可以归因于受政治紧张局势驱使的黑客活动分子。 众所周知&#xff0c;当今的黑…

Ubuntu22.04系统安装opencv步骤简述及问题解决方法

前言 opencv是一个功能强大、开源且跨平台的计算机视觉库&#xff0c;适用于多种编程语言和操作系统&#xff0c;能够帮助开发者构建各种视觉项目。其模块众多&#xff0c;提供了诸多功能&#xff0c;能够进行图像处理、视频处理等等。比如&#xff1a;Highgui模块提供图像用户…

java开发中间件学习记录(持续更新中~)

1 Redis 2JVM 3 java基础底层 4Mysql 5 spring 6 微服务 7.......(持续更新) One:Redis篇 1:Redis 1.穿透 1.1缓存穿透 1.1.1布隆过滤器 1.2缓存击穿 2&#xff1a;击穿 1.3&#xff1a;缓存雪崩 1.4:双写一致 1.5.持久化&#xff08;RDB,AOF&#xff09; 1.6…

Mastering openFrameworks_第十一章_网络

网络 网络为多个设备之间的数据交换提供了一种方式。它是一个主要组成部分&#xff0c;允许远程控制移动和平板设备应用程序中的一些参数&#xff0c;也用于使交互式项目在多台计算机上同步工作。在本章中&#xff0c;您将学习如何在openFrameworks项目中实现和使用OSC和TCP协…

Go 1.19.4 路径和目录-Day 15

1. 路径介绍 存储设备保存着数据&#xff0c;但是得有一种方便的模式让用户可以定位资源位置&#xff0c;操作系统采用一种路径字符 串的表达方式&#xff0c;这是一棵倒置的层级目录树&#xff0c;从根开始。 相对路径&#xff1a;不是以根目录开始的路径&#xff0c;例如 a/b…

【Qt笔记】QScrollArea控件详解

目录 引言 一、QScrollArea 的基本概念 二、QScrollArea 的主要属性 2.1 设置内容大小是否随滚动区域变化 2.2 设置水平与垂直滚动条 2.3 设置视口外边距 三、QScrollArea 的常用方法 3.1 设置显示小部件 3.2 返回当前设置的小部件 3.3 设置内部小部件是否可以填充…

【bug】通过lora方式微调sdxl inpainting踩坑

报错内容 ValueError: Attempting to unscale FP16 gradients. 报错位置 if accelerator.sync_gradients:params_to_clip (itertools.chain(unet_lora_parameters, text_lora_parameters_one, text_lora_parameters_two)if args.train_text_encoderelse unet_lora_parameters…

ICP算法介绍,机器人姿态估计,三维点云配准

介绍 ICP算法&#xff0c;即Iterative Closest Point&#xff08;迭代最近点&#xff09;算法&#xff0c;是一种广泛应用于计算机视觉和图像处理领域的几何配准算法。它的主要目的是通过最小化两组点集之间的距离来找出一组变换&#xff0c;使得两组点集尽可能地对齐。ICP算法…

37拼购:电商新风尚,共享双赢的购物革命

随着2024年电商市场的日益繁荣&#xff0c;商品海洋中的同质化问题愈发严峻&#xff0c;消费者在茫茫商海中寻觅独特价值的难度陡增。在此背景下&#xff0c;一种名为“37悦享拼”的创新电商模式横空出世&#xff0c;它巧妙融合了私域社交与电商精髓&#xff0c;旨在打破传统壁…

9.18作业

提示并输入一个字符串&#xff0c;统计该字符串中字母、数字、空格、其他字符的个数并输出 代码展示 #include <iostream>using namespace std;int main() {string str;int countc 0; // 字母计数int countn 0; // 数字计数int count 0; // 空格计数int counto 0;…

部署自己的对话大模型,使用Ollama + Qwen2 +FastGPT 实现

部署资源 AUTODL 使用最小3080Ti 资源&#xff0c;cuda > 12.0使用云服务器&#xff0c;部署fastGPT oneAPI&#xff0c;M3E 模型 操作步骤 配置代理 export HF_ENDPOINThttps://hf-mirror.com下载qwen2模型 - 如何下载huggingface huggingface-cli download Qwen/Qwen2-…

Java | Leetcode Java题解之第402题移掉K位数字

题目&#xff1a; 题解&#xff1a; class Solution {public String removeKdigits(String num, int k) {Deque<Character> deque new LinkedList<Character>();int length num.length();for (int i 0; i < length; i) {char digit num.charAt(i);while (!…

ERP进销存管理系统的业务全流程 Axure高保真原型源文件分享

这是一套ERP进销存管理系统的业务全流程Axure高保真原型设计文档。 原型预览地址&#xff1a;https://ppndif.axshare.com 产品意义&#xff1a; 提高工作效率&#xff1a; 电子记账替代手工记账&#xff0c;减少工作负担和人为错误。 实时查看库存情况&#xff0c;减少盘点时…

MySQL常用语句(一)

#数据库操作思路 #相关实验 <SQL语句简介> <web安全SQL语句基本操作> #数据库管理 #创建数据库 在与数据进行任何操作之前&#xff0c;需要创建一个数据库。数据库是数据的容器&#xff0c;用于存储和操作诸如表、数据库视图、触发器、存储过程等数据的数据集…

项目管理 | 一文读懂什么是敏捷开发管理

在快速变化的商业环境中&#xff0c;项目管理方式也在不断演进&#xff0c;其中敏捷开发管理因其高效、灵活和适应性强的特点&#xff0c;逐渐成为众多企业和团队的首选。本文将详细解析敏捷开发管理的定义、具体内容及其核心角色&#xff0c;帮助读者全面理解这一先进的项目管…

Alinx MPSoC驱动开发第17章I2C实验修改设备树后petalinux编译报错

问题描述 在使用Alinx的MPSoC Linux驱动开发手册第17章进行I2C驱动学习时&#xff0c;在按照手册&#xff0c;在system-user.dtsi文件最后添加引用i2c1节点内容&#xff1a; 然后使用petalinux-build命令进行编译&#xff0c;后报错如下&#xff1a; 尝试解决问题 1&#xff0c…

vscode软件在 C发中常用插件

一. 简介 本文简单介绍一下&#xff0c;当做 C开发时 vscode软件常用的插件。 vscode软件是 微软公司目前提供的一款免费的开发软件&#xff0c;可以通过 vscode官网下载 vscode。 二. vscode软件在 C开发中常用插件 注意&#xff1a;vscode软件安装后&#xff0c;可以直接…

FlinkCDC 3.2.0 新增优点 Pattern Replacement in routing rules

新增优点&#xff1a;Pattern Replacement in routing rules flinkcdc 3.2.0版本相较于3.1.0版本&#xff0c;避免了多表多sink多次写 route 路由的麻烦&#xff0c;类似于统一前后缀的形式多表多sink&#xff0c;通过<>正则&#xff0c;大大减少了书写 官网&#xff1…