021.合并两个有序链表,递归和遍历

news2024/10/6 22:34:05

题意

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

难度

简单

标签

链表、排序

示例

输入:l1 = [1,2,4], l2 = [1,3,4]
输出:[1,1,2,3,4,4]

输入:l1 = [], l2 = []
输出:[]

输入:l1 = [], l2 = [0]
输出:[0]
复制代码

分析 1

先来读题,关键词,两个升序链表,合并,一个新的升序链表。

既然升序过,那最小的数字肯定是两个链表l1和l2中头节点中的一个。

如果最小的是 l1 的头节点,那么第二小的节点肯定是l2的头节点或者l1.next,只要再比较一下两个的大小就能够得到第二小的节点。

如果最小的是 l2 的头节点,那么第二小的肯定是l1的头节点或者l2.next;

那我们就可以采用递归的方式:

if (l1.val < l2.val) {
	l1.next = mergeTwoLists(l1.next, l2);
	return l1;
} else {
	l2.next = mergeTwoLists(l1, l2.next);
	return l2;
}

如果 l1 的头节点小于 l2 的头节点,那么 l1 的 next 应该是 l1.next 或者 l2;

如果 l1 的头节点大于 l2 的头节点,那么 l2 的 next 应该是 l1 或者 l2.next;

每次递归调用都会返回当前两个链表头部较小的那个节点作为合并链表的当前节点。

递归的结束条件就是 l1 或者 l2 为空,那么返回另一个链表即可。因为如果其中一个链表为空,就意味着另一个链表已经是当前最终的排序链表了,我们可以直接返回非空链表作为合并后的链表。

// 如果 l1 为空,返回 l2
if (l1 == null) {
	return l2;
}
// 如果 l2 为空,返回 l1
if (l2 == null) {
	return l1;
}

OK,我们来看完整的题解:

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // 如果 l1 为空,返回 l2
        if (l1 == null) {
            return l2;
        }
        // 如果 l2 为空,返回 l1
        if (l2 == null) {
            return l1;
        }
        
        // 选择较小的节点,递归地合并剩余部分
        if (l1.val < l2.val) {
            l1.next = mergeTwoLists(l1.next, l2);
            return l1;
        } else {
            l2.next = mergeTwoLists(l1, l2.next);
            return l2;
        }
    }
}

递归的关键在于理解每一步递归调用都在做什么,以及递归何时结束。在这个问题中,每一步递归都在处理两个链表当前的头节点,并通过递归调用来处理剩下的节点。递归使得问题规模逐渐变小,直至达到简单的基本情况(一个链表为空),从而完成整个合并过程。

我们来看题解的效率:

分析 2

递归看起来简单,但对于新手来说,理解起来很痛苦,尤其是递归的调用栈,很深。。。深的脑子一片乱麻。

那我们换一种更直接的思路,直接遍历两个链表,依次比较两个链表的节点,将较小的节点放到新链表中。

然后移动指针,继续比较,直到其中一个链表为空,然后将另一个链表剩余的部分直接连接到新链表的末尾。

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        // 初始化哨兵节点
        ListNode sentinel = new ListNode(-1);
        // 初始化一个指针,最初指向哨兵节点
        ListNode prev = sentinel;
        
        // 当两个链表都不为空时,循环继续
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                prev.next = l1;
                l1 = l1.next;
            } else {
                prev.next = l2;
                l2 = l2.next;
            }
            // 移动prev指针
            prev = prev.next;
        }
        
        // 直接将非空链表剩余部分连接到新链表末尾
        prev.next = l1 == null ? l2 : l1;
        
        // 返回哨兵节点的下一个节点,即合并后链表的头节点
        return sentinel.next;
    }
}

/**
     * 用循环遍历的方式
     *
     * 直接遍历两个链表,依次比较两个链表的节点,将较小的节点放到新链表中。
     *
     * 然后移动指针,继续比较,直到其中一个链表为空,然后将另一个链表剩余的部分直接连接到新链表的末尾。
     * @param l1
     * @param l2
     * @return
     */
    public ListNode mergeTwoLists2(ListNode l1 ,ListNode l2){
        //1初始化哨兵节点
        ListNode sentinel = new ListNode(-1);
        //2初始化一个指针,最初指向哨兵节点
        ListNode prev = sentinel;
        //3当两个链表不为空时,循环遍历两个链表,用prev连接后续节点
        while (l1 != null&& l2 != null ){
            //找最小节点开头
            if (l1.val <=l2.val){
                //指针 链表的下一个节点为 l1 头节点
                prev.next = l1;
                //更新 l1 链表的节点,变成后一个节点
                l1 = l1.next;
            }else {
                prev.next = l2;
                //后移
                l2 = l2.next;
            }
            //移动prev  。。指向  指针链表的 下一个节点 指向的为 刚才 拼接上的节点
            prev = prev.next;
        }
        //直接将非空链表剩余部分连接到新建表末尾
        prev.next = l1 ==null ? l2:l1;
        // 返回哨兵节点的下一个节点,即合并后链表的头节点
        return sentinel.next;
    }

这个题解的效率也非常不错,但更容易理解一些:

总结

这道题目是链表的基础题,递归和迭代都可以解决,递归的思路更加简洁,但是对于新手来说,理解起来可能会有些困难,迭代的思路更加直接,但是代码量会多一些。

关键还是理解链表的数据结构,这个视频讲的不错,推荐一手。

视频链接:链表 数据结构与算法,完整代码动画版,附在线数据结构交互式工具_哔哩哔哩_bilibili

还有这个网站,对链表也进行了详细的讲解,推荐一手。

网站链接:4.2   链表 - Hello 算法

链表另外一个关键点在于理解指针的移动,比如说 prev = prev.next,这个操作不只是移动指针,还相当于删除了 prev 节点,大家可以感受一下。

力扣链接:. - 力扣(LeetCode)

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

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

相关文章

常用组件详解(二):torch.nn.Flatten、torch.flatten()

文章目录 torch.nn.Flattentorch.flatten() 官方API文档&#xff1a;点击跳转。torch.nn.Flatten是Pytorch提供的类&#xff0c;常用于将输入数据进行展平&#xff0c;而torch.flatten()函数与之功能相同。 torch.nn.Flatten 类初始化方式&#xff1a; torch.nn.Flatten(star…

微信小程序-自定义组件checkbox

一.自定义Coponent组件 公共组件&#xff1a;将页面内公共的模块抽取为自定义组件&#xff0c;在不同页面复用。 页面组件&#xff1a;将复杂页面进行拆分&#xff0c;降低耦合度&#xff0c;有利于代码维护。 可以新建文件夹component放组件&#xff1a; 组件名为custom-che…

(2024,频域 LoRA,DFT,DCT,自适应门控,基于适配器组合的图像编辑)FouRA:傅里叶 LoRA

FouRA: Fourier Low Rank Adaptation 公和众与号&#xff1a;EDPJ&#xff08;进 Q 交流群&#xff1a;922230617 或加 VX&#xff1a;CV_EDPJ 进 V 交流群&#xff09; 目录 0. 摘要 2. 相关工作 3. 提出的方法 3.1 低秩适应的公式 3.2 频域中的低秩适应 3.3 频率变换 …

三十九篇:UML与SysML:掌握现代软件和系统架构的关键

UML与SysML&#xff1a;掌握现代软件和系统架构的关键 1. 引言 1.1 为什么系统设计如此关键 在当今快速发展的技术环境中&#xff0c;系统设计的重要性不言而喻。无论是软件开发还是复杂的系统工程&#xff0c;良好的设计是确保项目成功的基石。系统设计不仅关系到功能的实现…

搜维尔科技:【研究】触觉手套比控制器更能带来身临其境、更安全、更高效的虚拟体验

自然交互可提高VR模拟的有效性。研究表明&#xff0c;触觉手套比控制器更能带来身临其境、更安全、更高效的虚拟体验。 以下是验证 医疗培训中的触觉技术 “ 95.5%的参与者表示触摸是 XR 教育的重要组成部分&#xff0c;90.9% 的参与者表示 XR 触觉将提供一个安全的学习场所。…

Hadoop 2.0 大家族(一)

目录 一、Hadoop 2.0大家族概述&#xff08;一&#xff09;分布式组件&#xff08;二&#xff09;部署概述 二、ZooKeeper&#xff08;一&#xff09;ZooKeeper简介&#xff08;二&#xff09;ZooKeeper 入门 一、Hadoop 2.0大家族概述 &#xff08;一&#xff09;分布式组件 …

Mybatis 系列全解(2)——全网免费最细最全,手把手教,学完就可做项目!

Mybatis 系列全解&#xff08;2&#xff09; 1. ResultMap结果集映射2. 日志2.1 日志工厂2.2 log4j 3. 分页3.1 实现SQL分页3.2 RowBounds 分页3.3 分页插件 4. 使用注解开发4.1 面向接口编程4.2 使用注解4.3 Mybatis 详细执行过程4.4 CRUD 增删改查 5. Lombok 1. ResultMap结果…

Android Studio中HAXM安装失败的解决方案(HAXM installation failed)

文章目录 错误示例Hyper-VWindows SandboxWindows Hypervisor Platform&#xff08;Windows 虚拟化监控程序平台&#xff09; 出现原因解决方法虚拟机平台方案一方案二方案三 错误示例 表明HAXM (Hardware Accelerated Execution Manager)安装失败了。HAXM是一个硬件辅助虚拟化…

查询DBA_TEMP_FILES报错,删除临时表空间报错ORA-60100

SYMPTOMS 查询DBA_TEMP_FILES报错如下图 ORA-01157: cannotidentify/ock data fle 201 -see DBWR trace fle ORA-01110: data fle 20 1: D:APPADMINISTRATORIORADATA MARTIDATAFILE 01157,00000-"cannotidentify/ock data fle %s -see DBWR trace fle"*Cause: The b…

番外篇 | YOLOv8改进之利用轻量化卷积PConv引入全新的结构CSPPC来替换Neck网络中的C2f | 模型轻量化

前言:Hello大家好,我是小哥谈。本文使用轻量化卷积PConv替换Neck中C2f模块中Bottleneck里的传统卷积核得到CSPPC模块,使得模型更加轻量化。🌈 目录 🚀1.基础概念 🚀2.网络结构 🚀3.添加步骤 🚀4.改进方法 🍀🍀步骤1:block.py文件修改 🍀🍀步…

【MySQL】数据库事务详解

文章目录 前言1. 事务的定义2. 事务的四个特性2.1 原子性2.2 一致性2.3 隔离性2.4 持久性 3. 事务的并发问题3.1 脏读3.2 不可重复读3.3 幻读3.4 更新丢失 4. 事务的隔离级别5. 事务的使用结语 前言 假设我们现在需要操作数据库进行转账&#xff0c;A 给 B 转账 100 块钱&…

【Text2SQL 论文】MCS-SQL:利用多样 prompts + 多项选择来做 Text2SQL

论文&#xff1a;MCS-SQL: Leveraging Multiple Prompts and Multiple-Choice Selection For Text-to-SQL Generation ⭐⭐⭐ arXiv:2405.07467 一、论文速读 已有研究指出&#xff0c;在使用 LLM 使用 ICL 时&#xff0c;ICL 的 few-shot exemplars 的内容、呈现顺序都会敏感…

Apple - View Programming Guide

本文翻译整理自&#xff1a;View Programming Guide&#xff08;更新&#xff1a;2013-08-08 https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/CocoaViewsGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40002978-CH1-SW1 文章目录…

Java学习笔记(多线程):CompetableFuture

本文是自己的学习笔记&#xff0c;主要参考资料如下 https://www.cnblogs.com/dolphin0520/p/3920407.html JavaSE文档 https://blog.csdn.net/ThinkWon/article/details/102508721 1、Overview2、重要参数3、主要方法3.1、创建实例&#xff0c;获取返回值3.2、线程执行顺序相关…

基于Springboot+Vue的校友社交系统(带1w+文档)

基于SpringbootVue的校友社交系统(带1w文档) 校友社交系统作为一种典型的管理系统也迅速的发展并深入人们的日常生活中&#xff0c;它使用户足不出户就可以管理自己的校友社交信息等&#xff0c;最大化减缩了用户的管理时间&#xff0c;提高了管理效率。 项目简介 基于SSMVUE的…

【TB作品】MSP430G2553,单片机,口袋板, 烘箱温度控制器

题3 烘箱温度控制器 设计一个基于MSP430的温度控制器&#xff0c;满足如下技术指标&#xff1a; &#xff08;1&#xff09;1KW 电炉加热&#xff0c;最度温度为110℃ &#xff08;2&#xff09;恒温箱温度可设定&#xff0c;温度控制误差≦2℃ &#xff08;3&#xff09;实时显…

llm-universe | 四. 构建RAG应用

构建RAG应用 一.将LLM 接入 LangChain二.构建检索问答链1.加载向量数据库2.创建一个 LLM3.构建检索问答链4.检索问答链效果测试5.添加历史对话的记忆功能5.1 记忆&#xff08;Memory&#xff09;5.2 对话检索链&#xff08;ConversationalRetrievalChain&#xff09; 三. 部署知…

【论文阅读】-- Temporal Summary Images:通过交互式注释生成和放置实现叙事可视化的方法

Temporal Summary Images: An Approach to Narrative Visualization via Interactive Annotation Generation and Placement 摘要1 引言2 背景及相关工作2.1 叙事可视化和讲故事2.2 显示面向时间的数据2.3 小倍数和漫画2.4 注释可视化 3 设计要求和工作流程3.1 工作流程3.2 TSI…

input()函数——输入

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 语法参考 input()函数可以提示并接收用户的输入&#xff0c;将所有的输入按照字符串进行处理&#xff0c;并返回一个字符串&#xff0c;input()函数的…

C3P0数据库连接池

目录 一&#xff1a;连接池介绍 1.1连接池解决的问题 2.常用的数据库连接池 二&#xff1a;c3p0介绍 2.1C3P0介绍&#xff1a; 2.2C3P0快速入门 1.常用参数说明 2.API介绍 3.使用步骤 1.导入jar包c3p0-0.9.1.2.jar 2.编写c3p0-config.xml配置文件&#xff0c;配置对…