【算法训练-链表】合并两个有序链表、合并K个有序链表

废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!首先,链表对应的数据结构在这篇Blog中:【基本数据结构 一】线性数据结构:链表,基于对基础知识的理解来进行题目解答。本篇Blog的主题是合并有序链表,近半年考察还是比较多的
在这里插入图片描述

合并两个有序链表

先来个基础版,合并两个已排序的链表

题干

在这里插入图片描述

输入:
{1,3,5},{2,4,6}返回值:
{1,2,3,4,5,6}
输入:
{},{}返回值:
{}
输入:
{-1,2,4},{1,3,4}返回值:
{-1,1,2,3,4,4}

解题思路

整体目标就是在两个链表中选节点来构建新链表

  1. 设置result为哨兵结点,放置于新链表之前,最后返回的就是dummy.next
  2. 设置cur为当前节点,从dummy开始,当两个链表都非空时进入循环,令新链表的下一个节点cur.next为val更小的节点,相应的链表节点后移一位,每次循环记得cur也要后移一位
  3. 如果循环结束后还有链表非空,cur指向非空链表,返回dummy.next

如下图所示:
在这里插入图片描述

解题代码

Java实现

import java.util.*;/** public class ListNode {*   int val;*   ListNode next = null;*   public ListNode(int val) {*     this.val = val;*   }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param pHead1 ListNode类* @param pHead2 ListNode类* @return ListNode类*/public ListNode Merge (ListNode pHead1, ListNode pHead2) {// 1 如果其中一个为空列表,直接返回另一个if (pHead1 == null && pHead2 == null) {return null;}if (pHead1 == null) {return pHead2;}if (pHead2 == null) {return pHead1;}// 2 定义哨兵节点用来返回最终链表,cur用来检索两个链表的较小值节点ListNode dummy = new ListNode(-1);ListNode cur = dummy;while (pHead1 != null && pHead2 != null) {if (pHead1.val <= pHead2.val) {cur.next = pHead1;pHead1 = pHead1.next;} else {cur.next = pHead2;pHead2 = pHead2.next;}cur = cur.next;}// 3 一个链表空后,直接将另一个链表剩余部分拼接if (pHead1 == null) {cur.next = pHead2;}if (pHead2 == null) {cur.next = pHead1;}return dummy.next;}
}

时间复杂度O(N+M):M N分别表示pHead1, pHead2的长度; 空间复杂度O(1):常数级空间

合并K个有序链表

OK,难度升级,两个变成K个有序链表进行合并

题干

在这里插入图片描述

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

解题思路

归并排序是什么?简单来说就是将一个数组每次划分成等长的两部分,对两部分进行排序即是子问题。对子问题继续划分,直到子问题只有1个元素。还原的时候呢,将每个子问题和它相邻的另一个子问题利用上述双指针的方式,1个与1个合并成2个,2个与2个合并成4个,因为这每个单独的子问题合并好的都是有序的,直到合并成原本长度的数组。

对于这k个链表,就相当于上述合并阶段的k个子问题,需要划分为链表数量更少的子问题,直到每一组合并时是两两合并,然后继续往上合并,这个过程基于递归:

  • 终止条件: 划分的时候直到左右区间相等或左边大于右边。
  • 返回值: 每级返回已经合并好的子问题链表。
  • 本级任务: 对半划分,将划分后的子问题合并成新的链表。

具体做法:

  1. 步骤一:从链表数组的首和尾开始,每次划分从中间开始划分,划分成两半,得到左边n/2个链表和右边n/2个链表
  2. 步骤二:继续不断递归划分,直到每部分链表数为1.
  3. 步骤三:将划分好的相邻两部分链表,按照两个有序链表合并的方式合并,合并好的两部分继续往上合并,直到最终合并成一个链表。

如下图所示,先进行合并链表划分
在这里插入图片描述
划分完子问题,子问题处理完返回到上一层级
在这里插入图片描述

解题代码

Java实现代码

import java.util.*;/** public class ListNode {*   int val;*   ListNode next = null;*   public ListNode(int val) {*     this.val = val;*   }* }*/public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param lists ListNode类ArrayList* @return ListNode类*/public ListNode mergeKLists (ArrayList<ListNode> lists) {return divideMerge(lists, 0, lists.size() - 1);}private ListNode divideMerge(ArrayList<ListNode> lists, int left, int right) {if (left > right) {return null;}// 终止条件,拿到了单独的链表if (left == right) {return lists.get(left);}int mid = (left + right) / 2;// 对两个相邻链表进行合并return merge(divideMerge(lists, left, mid), divideMerge(lists, mid + 1, right));}private ListNode merge(ListNode pHead1, ListNode pHead2) {// 1 链表非空判断if (pHead1 == null && pHead2 == null) {return null;}if (pHead1 == null) {return pHead2;}if (pHead2 == null) {return pHead1;}// 2 定义哨兵节点和最终返回链表ListNode dummy = new ListNode(-1);ListNode cur = dummy;while (pHead1 != null && pHead2 != null) {if (pHead1.val <= pHead2.val) {cur.next = pHead1;pHead1 = pHead1.next;} else {cur.next = pHead2;pHead2 = pHead2.next;}cur = cur.next;}// 3 如果一个链表空了,直接挂载另一个链表剩余节点if (pHead1 == null) {cur.next = pHead2;}if (pHead2 == null) {cur.next = pHead1;}return dummy.next;}
}

时间复杂度:O(nlogk),其中n为所有链表的总节点数,分治为二叉树型递归,最坏情况下二叉树每层合并都是O(n)个节点,而分治次数为:O(logk),所以总的时间复杂度就是O(nlogk)

空间复杂度:最坏情况下合并O(logk),所以递归栈的深度为O(logk)

拓展:递归和分治的区别

递归(Recursion)和分治(Divide and Conquer)是两种解决问题的方法,它们有一些相似之处,但也存在一些关键的区别。

递归(Recursion)
递归是一种问题解决方法,其中函数在其执行过程中调用自身来解决更小规模的子问题,直到达到基本情况,然后逐层返回结果以构建原始问题的解。递归的核心思想是将一个大问题划分为与原问题结构相同但规模更小的子问题,然后通过逐步解决这些子问题来解决原始问题。

分治(Divide and Conquer)
分治是一种将问题分解为多个相互独立的子问题,然后解决这些子问题并将它们的解合并以得到原始问题解的方法。分治的核心思想是将一个大问题划分为多个独立的子问题,这些子问题可以并行地解决,然后将它们的解合并起来以得到原问题的解。

关键区别:

  1. 目标

    • 递归的目标是通过将问题分解为与原问题结构相同但规模更小的子问题,然后逐层解决这些子问题来得到原问题的解。
    • 分治的目标是将问题分解为多个相互独立的子问题,然后并行地解决这些子问题,并将它们的解合并以得到原问题的解。
  2. 子问题之间的关系

    • 递归中,子问题之间的关系通常是相同结构的,但规模不同。
    • 分治中,子问题通常是相互独立的,没有交叉。
  3. 解决方式

    • 递归解决问题时,通常需要考虑如何将问题分解为更小的子问题,然后将这些子问题的解组合起来。
    • 分治解决问题时,通常需要考虑如何将问题分解为独立的子问题,然后并行地解决这些子问题,最后将它们的解合并起来。
  4. 合并过程

    • 递归中,解决子问题的过程是逐层递归地调用函数,然后逐层返回结果。
    • 分治中,解决子问题的过程可以并行地进行,然后将子问题的解合并。

总的来说,递归和分治都是将复杂问题分解为更小的部分来解决的方法,但它们的关注点和执行方式有所不同。在实际应用中,有时候递归和分治可以结合使用,例如在分治算法的子问题解决过程中使用递归。

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

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

相关文章

Vue2向Vue3过度Vuex状态管理工具快速入门

目录 1 Vuex概述1.是什么2.使用场景3.优势4.注意&#xff1a; 2 需求: 多组件共享数据1.创建项目2.创建三个组件, 目录如下3.源代码如下 3 vuex 的使用 - 创建仓库1.安装 vuex2.新建 store/index.js 专门存放 vuex3.创建仓库 store/index.js4 在 main.js 中导入挂载到 Vue 实例…

0821|C++day1 初步认识C++

一、思维导图 二、知识点回顾 【1】QT软件的使用 1&#xff09;创建文件 创建文件时&#xff0c;文件的路径一定是全英文 2&#xff09;修改编码 工具--->选项--->行为--->默认编码&#xff1a;system 【2】C和C的区别 C又叫C plus plus&#xff0c;C是对C的扩充&…

交通科技与管理杂志社交通科技与管理编辑部2023年第9期目录

专家论坛 黑龙江省经济高质量发展与生态环境保护耦合协调发展研究 刘降斌;祃玉帅; 1-5142 我国省际数字经济高质量发展水平综合评价研究 耿娟;毕晨曦; 6-8 振兴龙江《交通科技与管理》投稿邮箱&#xff1a;cn7kantougao163.com(注明投稿“《交通科技与管理》”) 数…

基于单片机的智能数字电子秤proteus仿真设计

一、系统方案 1、当电子称开机时&#xff0c;单片机会进入一系列初始化&#xff0c;进入1602显示模式设定&#xff0c;如开关显示、光标有无设置、光标闪烁设置&#xff0c;定时器初始化&#xff0c;进入定时器模式&#xff0c;如初始值赋值。之后液晶会显示Welcome To Use Ele…

性能优化维度

CPU 首先检查 cpu&#xff0c;cpu 使用率要提升而不是降低。其次CPU 空闲并不一定是没事做&#xff0c;也有可能是锁或者外部资源瓶颈。常用top、vmstat命令查看信息。 vmstat 命令: top: 命令 IO iostat 命令&#xff1a; Memory free 命令&#xff1a; 温馨提示&#xff1a…

【悬挂绝缘子的串效模型】测量每个绝缘子盘之间的电压并测量串效研究(Simulink)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

无可用的防病毒提供方你的设备

今天安装软件时关闭了一下windows的Defender&#xff0c;然后安装后出现下面问题 莫名奇妙我的病毒防护就不能用了 后来请教了老师才知道是安装的软件把我系统设置改了&#xff0c;以后使用一键安装软件要谨慎 解决措施&#xff1a; CMD命令&#xff0c;输入“regedit”&#…

SpringCloud Alibaba实战和源码(7)Skywalking

什么是SkyWalking Skywalking是由国内开源爱好者吴晟开源并提交到Apache孵化器的产品&#xff0c;它同时吸收了Zipkin /Pinpoint /CAT 的设计思路。特点是&#xff1a;支持多种插件&#xff0c;UI功能较强&#xff0c;支持非侵入式埋点。目前使用厂商最多&#xff0c;版本更新较…

UE4/5Niagara粒子特效之Niagara_Particles官方案例:2.4->3.2

之前的案例 UE4/5Niagara粒子特效之Niagara_Particles官方案例&#xff1a;1.1-&#xff1e;1.4_多方通行8的博客-CSDN博客 UE4/5Niagara粒子特效之Niagara_Particles官方案例&#xff1a;1.5-&#xff1e;2.3_多方通行8的博客-CSDN博客 2.4 Location Events 这次的项目和之…

升级Go 版本到 1.19及以上,Goland: file.Close() 报错: Unresolved reference ‘Close‘

错误截图 解决方法 File -> Settings -> Go -> Build Tags & Vendoring -> Custom tags -> 添加值 “unix” 原因 Go 1.19 引入了unix构建标签。因此&#xff0c;需要添加unix到自定义标签。 参考 https://blog.csdn.net/weixin_43940592/article/det…

学习JAVA打卡第四十四天

Scanner类 ⑴Scanner对象 scanner对象可以解析字符序列中的单词。 例如&#xff1a;对于string对象NBA 为了解析出NBA的字符序列中的单词&#xff0c;可以如下构造一个scanner对象。 将正则表达式作为分隔标记&#xff0c;即让scanner对象在解析操作时把与正则表达式匹配的字…

通过WinFsp将linux目录映射到windows下,ubuntu开启SSH服务,并允许ROOT权限远程登录,WinFsp使用教程;

一、在windows下的准备工作&#xff1a; 1.下载并安装 Download WinFsp Installer 和 SSHFS-Win(x64)&#xff0c;直接安装就行一路默认&#xff1b; 下载地址&#xff1a;点击此处下载https://winfsp.dev/rel/ 二、在linux下的准备工作(本人使用的是Ubuntu)&#xff1a; 1.…

7.11 SpringBoot实战 全局异常处理 - 深入细节详解

文章目录 前言一、异常分类1.1 业务异常1.2 参数校验异常1.3 通用异常兜底 二、保留异常现场2.1 请求地址2.2 请求header2.3 请求参数body2.4 构建异常上下文消息 最后 前言 全局异常处理, 你真的学会了吗&#xff1f; 学完上文&#xff0c;你有思考和动手实践吗&#xff1f;…

阿里云将关停代销业务

我是卢松松&#xff0c;点点上面的头像&#xff0c;欢迎关注我哦&#xff01; 阿里云自从逐渐分拆独立之后&#xff0c;做了很多调整。最近它又做了一个大动作&#xff1a;据DoNews消息&#xff0c;阿里云将会在今年9月30日之前&#xff0c;全面关停代销业务。 这件事实际上…

企业网络日志安全与 EventLog Analyzer

企业的网络日志安全是一项至关重要的任务。随着信息技术的迅猛发展&#xff0c;网络攻击和数据泄露的威胁也与日俱增。为了应对这些威胁&#xff0c;企业需要强大的工具来监控、分析和保护其网络日志。而ManageEngine的EventLog Analyzer正是这样一款卓越的解决方案。 网络日志…

Mr. Cappuccino的第64杯咖啡——Spring循环依赖问题

Spring循环依赖问题 什么是循环依赖问题示例项目结构项目代码运行结果 Async注解导致的问题使用Lazy注解解决Async注解导致的问题开启Aop使用代理对象示例项目结构项目代码运行结果 Spring是如何解决循环依赖问题的原理源码解读 什么情况下Spring无法解决循环依赖问题 什么是循…

UbuntuDDE 23.04发布,体验DeepinV23的一个新选择

UbuntuDDE 23.04发布&#xff0c;体验DeepinV23的一个新选择 昨晚网上搜索了一圈&#xff0c;无意看到邮箱一条新闻&#xff0c;UbuntuDDE 23.04发布了 因为前几天刚用虚拟机安装过&#xff0c;所以麻溜的从网站下载了ISO文件&#xff0c;安装上看看。本来没多想&#xff0c;…

设计模式--单例模式(Singleton Pattern)

一、什么是单例模式 单例模式是一种创建型设计模式&#xff0c;它旨在确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。换句话说&#xff0c;单例模式限制了类的实例化次数为一个&#xff0c;并提供一种在应用程序中共享一个实例的方式。这对于需要只有…

2023年高教社杯 国赛数学建模思路 - 案例:FPTree-频繁模式树算法

文章目录 算法介绍FP树表示法构建FP树实现代码 建模资料 ## 赛题思路 &#xff08;赛题出来以后第一时间在CSDN分享&#xff09; https://blog.csdn.net/dc_sinor?typeblog 算法介绍 FP-Tree算法全称是FrequentPattern Tree算法&#xff0c;就是频繁模式树算法&#xff0c…

FxFactory 8 Pro Mac 苹果电脑版 fcpx/ae/motion视觉特效软件包

FxFactory pro for mac是应用在Mac上的fcpx/ae/pr视觉特效插件包&#xff0c;包含了成百上千的视觉效果&#xff0c;打包了很多插件&#xff0c;如调色插件&#xff0c;转场插件&#xff0c;视觉插件&#xff0c;特效插件&#xff0c;文字插件&#xff0c;音频插件&#xff0c;…