C/C++ BM5 合并K个已排序的链表

文章目录

  • 前言
  • 题目
  • 1 解决方案一
    • 1.1 思路阐述
    • 1.2 源码
  • 2 解决方案二
    • 2.1 思路阐述
    • 2.2 源码
  • 总结

前言

在接触了BM4的两个链表合并的情况,对于k个已排序列表,其实可以用合并的方法来看待问题。

这里第一种方法就是借用BM4的操作,只不过是多个合并的情况。

第二种方法是把所有的链表变成一个链表,再排序输出。调用STL库的话,这题就很取巧了。


题目

在这里插入图片描述

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

数据范围:节点总数 0≤n≤5000,每个节点的val满足 ∣val∣<=1000
要求:时间复杂度 O(nlogn)
示例1
输入:[{1,2,3},{4,5,6,7}]
返回值:{1,2,3,4,5,6,7}

示例2
输入:[{1,2},{1,4,5},{6}]
返回值:{1,1,2,4,5,6}

1 解决方案一

1.1 思路阐述

这个方案主要就是借助BM4的解法,无论哪一种都行。将原来两个链表的表变成,一个链表与一个存放链表容器中的每一个链表合并的过程。

比如对于vector容器lists,存放链表。对于lists[0]和lists[1]两个链表,在BM4中就是对应的两个有序链表合并;合并后的链表这里简称finalList,接下来就是这个finalList和lists容器中的下一个链表进行合并。重复上面的操作,直到容器内取完所有链表。

这里finalList是一个哨兵节点,是为了保证实际链表中的每一个节点都有前驱结点。

1.2 源码

#include <cstdlib>
#include <vector>
class Solution {
  public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
        //如果为空则返回空
        if(!lists.size())
            return nullptr;
        
        ListNode* finalList=new ListNode(-1);
        finalList->next=lists[0];

		//这里i为什么从1开始,是因为lists[0]作为finalList的初始链表了
        for(int i=1;i<lists.size();i++)
        {
            //int j=i+1;
            finalList->next=Merge(finalList->next,lists[i]) ;               
        }
        return finalList->next;
    }
    //下面的这个Merge函数就是BM4的一个解法,BM4有两个解法,这里我挑了一个比较好理解的。
    ListNode* Merge(ListNode* pHead1, ListNode* pHead2) {
        ListNode* rec = new ListNode(-1);
        if (!pHead1 && !pHead2) {
            return nullptr;
        }
        if (!pHead1 && pHead2) {
            return pHead2;
        }
        if (pHead1 && !pHead2) {
            return pHead1;
        }
        //比较链表大小
        bool firstListBig = true;
        if (pHead1->val > pHead2->val) {
            firstListBig = true;
            rec->next = pHead2;
        } else {
            firstListBig = false;
            rec->next = pHead1;
        }

        //第二个链表大的情况
        if (!firstListBig) {
            while (pHead2 && pHead1) {
                if (!pHead1->next) {
                    pHead1->next = pHead2;
                    break;
                }
                ListNode* tempNode = pHead2->next;
                if (pHead2->val <= pHead1->next->val) {
                    pHead2->next = pHead1->next;
                    pHead1->next = pHead2;
                    pHead2 = tempNode;
                    pHead1 = pHead1->next;
                } else {
                    pHead1 = pHead1->next;
                    if (!pHead1->next) {
                        pHead1->next = pHead2;
                        break;
                    }
                }
            }

        } else { //第二个链表小的情况
            while (pHead2 && pHead1) {
                if (!pHead2->next) {
                    pHead2->next = pHead1;
                    break;
                }
                ListNode* tempNode = pHead1->next;
                if (pHead1->val <= pHead2->next->val) {
                    pHead1->next = pHead2->next;
                    pHead2->next = pHead1;
                    pHead1 = tempNode;
                    pHead2 = pHead2->next;
                } else {
                    pHead2 = pHead2->next;
                    if (!pHead2->next) {
                        pHead2->next = pHead1;
                        break;
                    }
                }
            }
        }
        return rec->next;
    }


};

2 解决方案二

2.1 思路阐述

不考虑BM4的解法,这道题拿到手的第一反应,有一堆链表要合并成一个升序链表。

那最简单的方法不就是把所有链表接到一起,再用排序算法做一下咯。

这里的难点吧,我个人绝对就是对stl的使用熟练与否,以及对于特殊情情况空链表的话,怎么判断。

在C++中,std::vector 是标准模板库(STL)提供的动态数组容器。它提供了动态大小的数组,可以在运行时动态地增加或减少其大小。std::vector 是一个非常灵活和常用的容器,用于存储一系列元素。

std::vector 是一个非常常用的容器,特别适合需要频繁访问元素、动态改变大小的情况。需要注意的是,由于在中间或头部插入/删除元素的代价相对较高,如果需要频繁在中间插入或删除元素,可能需要考虑其他容器,比如 std::list。

2.2 源码

#include <cstdlib>
#include <vector>
#include <algorithm>
class Solution {
  public:
    ListNode* mergeKLists(vector<ListNode*>& lists) {
    	//用来返回的容器
        vector <int> vec;
        //如果传入的链表容器为空则直接返回
        if (lists.size() == 0)
            return NULL;
        //将链表容器的链表中的所有值插入到返回容器vec中
        for (int i = 0; i < lists.size(); ++i) {
            ListNode* p = lists[i];
            while (p) {
                vec.push_back(p->val);
                p = p->next;
            }
        }
        //使用stl容器库的sort(这个是快排)
        sort(vec.begin(), vec.end());
        //对于链表容器是空的情况,虽然size>0,但是插入到vec的值其实还是空的,所以这里还要返回NULL
        if (vec.size() == 0)
            return NULL;
        //把vec的所有值全部放到新的链表中去,返回一个新的链表即可。
        ListNode* head = new ListNode(vec[0]);
        ListNode* p = head;
        for (int i = 1; i < vec.size(); ++i) {
            p->next = new ListNode(vec[i]);
            p = p->next;
        }
        return head;
    }



};

总结

这道题是BM4的延伸,主要是多了一个两两合并的思想,对于解法二,就是有点取巧的意思了,就题论题这种。

对于解法2的sort,涉及到的是排序算法:快速排序。这个后面还是要自己手写一遍快排。

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

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

相关文章

腾讯云服务器的介绍_云主机概览——腾讯云

腾讯云服务器CVM提供安全可靠的弹性计算服务&#xff0c;腾讯云明星级云服务器&#xff0c;弹性计算实时扩展或缩减计算资源&#xff0c;支持包年包月、按量计费和竞价实例计费模式&#xff0c;CVM提供多种CPU、内存、硬盘和带宽可以灵活调整的实例规格&#xff0c;提供9个9的数…

workflow源码解析:GoTask

关于go task 提供了另一种更简单的使用计算任务的方法&#xff0c;模仿go语言实现的go task。 使用go task来实计算任务无需定义输入与输出&#xff0c;所有数据通过函数参数传递。 与ThreadTask 区别 ThreadTask 是有模板&#xff0c;IN 和 OUT&#xff0c; ThreadTask 依赖…

分布式Erlang/OTP(学习笔记)(一)

Erlang分布式基础 假设你在机器A和机器B上各跑着一个Simple Cache应用的实例。要是在机器A的缓存上插人一个键/值对之后&#xff0c;从机器B上也可以访问&#xff0c;那可就好了。显然&#xff0c;要达到这个目的&#xff0c;机器A必须以某种方式将相关信息告知给机器B。传递该…

力扣309. 买卖股票的最佳时机含冷冻期(动态规划,Java C++解法)

Problem: 309. 买卖股票的最佳时机含冷冻期 文章目录 题目描述思路解题方法复杂度Code 题目描述 思路 Problem: 714. 买卖股票的最佳时机含手续费 该题目可以看作是上述题目的改编&#xff0c;该题目添加了一个冷冻期使得动态转移方程更加复杂&#xff0c;具体思路如下&#xf…

【MyBatis-Plus】逻辑删除

对于一些比较重要的数据&#xff0c;我们通常采用逻辑删除。&#xff08;即用一个字段表示是否删除&#xff0c;实际上始终在数据库没有被删除&#xff09; 当逻辑删除字段为 true&#xff0c;业务处理的时候会自动把该数据当做一个“不存在”的数据处理。&#xff08;即不处理…

uniapp让图片缩小

image{width: 500rpx;height:500rpx;} 在图片属性设置为image{}宽高改变但是大小不改变&#xff0c;解决办法是改成下面的代码 & > img {width: 50px; height: auto; } 如图&#xff1a;

最优解:阿里云服务器地域如何选择?

阿里云服务器地域和可用区怎么选择&#xff1f;地域是指云服务器所在物理数据中心的位置&#xff0c;地域选择就近选择&#xff0c;访客距离地域所在城市越近网络延迟越低&#xff0c;速度就越快&#xff1b;可用区是指同一个地域下&#xff0c;网络和电力相互独立的区域&#…

【计算机网络】(1)OSI七层模型、协议、交换技术、路由器技术

文章目录 计算机网络功能与分类计算机网络的定义计算机网络的功能计算机网络的指标计算机网络的性能指标计算机网络的非性能指标 计算机网络的分布范围以及拓扑结构划分图计算机网络分类总线型拓扑星型拓扑环形图拓扑树型拓扑分布式拓扑 通信技术信道物理信道逻辑信道 发信机OS…

vue3-事件处理

事件监听 DOM 事件监听指令 v-on 简写 v-on:click"handler" 或者 click"handler"事件处理器 (handler) 的值可以是&#xff1a; 内联事件处理器&#xff1a;比如 click 方法事件处理器&#xff1a;一个指向组件上定义的方法的属性名或是路径。 在内联…

搭建属于自己的内容付费平台:开发知识付费APP教学

近期知识付费的热度非常高&#xff0c;本篇文章小编将为你提供一份关于如何搭建属于自己的内容付费平台的简要教程&#xff0c;让你能够逐步实现一个功能完备的知识付费APP。 1.明确目标和功能需求 在开始开发之前&#xff0c;首先需要确定你的APP是面向哪个领域的用户&#x…

JSONObject - 用最通俗的讲解,教你玩转 JSON 数据的解析和修改

目录 一、JSONObject 1.1、为什么要使用他&#xff1f; 1.2、应用 1.2.1、依赖 1.2.2、JSON 数据示例 1.2.3、JSON 数据的构建 1.2.4、JSON 数据的解析 一、JSONObject 1.1、为什么要使用他&#xff1f; 在还没有接触过这个东西的时候&#xff0c;一直是通过 ObjectMap…

保护国家机密:Java国密加解密算法在信息安全中的应用与挑战

目录 1、简介 1.1 信息安全的重要性 1.2 Java国密加解密算法的概述 2、Java国密加解密算法的应用 2.1 数据加密与解密 2.2 网络通信加密 2.3 数字签名与验证 2.4 安全存储与传输 3、Java国密加解密算法的特点 3.1 安全性强 3.2 效率高 3.3 弹性可调 4、Java国密加…

(2024,密集量子电路,量子 U-Net,幺正单采样)量子去噪扩散模型

Quantum Denoising Diffusion Models 公和众和号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 2. 相关工作 2.1. 扩散模型 2.2. 变分量子电路 2.3. 量子扩散模型 3. 量子去噪扩散模…

HarmonyOS 转场动画 ForEach控制

本文 我们继续说组件的专场特效 上文 HarmonyOS 转场动画 我们通过if控制了转场效果 本文 我们通过 ForEach 控制它的加载和删除 这时候就有人会好奇 ForEach 怎么控制删除呢&#xff1f; 很简单 循环次数不同 例如 第一次 10个 第二次 5个 那么后面的五个就相当于删除啦 我们…

JVM垃圾回收机制及思维导图

一、Java垃圾回收机制 在java中&#xff0c;程序员是不需要显示的去释放一个对象的内存的&#xff0c;而是由虚拟机自行执行。在JVM中&#xff0c;有一个垃圾回收线程&#xff0c;它是低优先级的&#xff0c;在正常情况下是不会执行的&#xff0c;只有在虚拟机空闲或者当前堆内…

【Alibaba工具型技术系列】「EasyExcel技术专题」实战技术针对于项目中常用的Excel操作指南

这里写目录标题 EasyExcel教程Maven依赖 EasyExcel API分析介绍EasyExcel 注解通用参数ReadWorkbook&#xff08;理解成excel对象&#xff09;参数ReadSheet&#xff08;就是excel的一个Sheet&#xff09;参数注解参数通用参数 WriteWorkbook&#xff08;理解成excel对象&#…

k8s学习-Deployment

Kubernetes通过各种Controller来管理Pod的生命周期 。 为了满足不同业 务 景 &#xff0c; Kubernetes 开发了Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job等多种Controller。我们⾸先学习最常用Deployment。 1.1 Kubectl命令直接创建 第一种是通过kubectl命令直接…

java读取配置文件数据

在实际开发中&#xff0c;项目中难免会有一些秘钥或者不经常使用到的配置信息&#xff0c;此时&#xff0c;就可以将这些配置信息统一写到配置文件中。随后使用Value注解读取配置文件的值来向Spring中Bean的属性设置值。 例如&#xff0c;一些系统环境变量信息&#xff0c;数据…

路飞项目--02

补充&#xff1a;axios封装 # 普通使用&#xff1a;安装 &#xff0c;导入使用 const filmListreactive({result:[]}) axios.get().then() async function load(){let responseawait axios.get()filmList.resultresponse.data.results } # 封装示例&#xff1a;请求发出去之前…

让代码运行得更快:深入理解进程、线程和协程

让代码运行得更快&#xff1a;深入理解进程、线程和协程 什么是执行体 在深入探讨进程、线程和协程之前&#xff0c;我想先介绍下执行体这个概念。 执行体这个词语是我从七牛云创始人许式伟大佬的专栏中学到的&#xff0c;它代表操作系统中程序执行的载体&#xff0c;涉及到…