首页 > 其他分享 >21. 合并两个有序链表

21. 合并两个有序链表

时间:2024-06-13 09:44:29浏览次数:22  
标签:ListNode 21 next 链表 有序 listNode1 节点 listNode2

题目链接

一、题目描述

1. 题目

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

2. 示例

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

示例 2:
输入:l1 = [], l2 = []
输出:[]

示例 3:
输入:l1 = [], l2 = [0]
输出:[0]

3. 提示

  • 两个链表的节点数目范围是[0, 50]
  • l1 和 l2 均按非递减顺序排列
  • -100 <= Node.val <= 100

二、代码实现

1. 递归

1.1 解题思路

链表、树、图相关的算法首先想递归。递归相关的知识见我的另一篇文章迭代与递归

递归设计函数的步骤:
1. 找重复: 找到的相同的子问题。

如下图,可以得出子问题为,l1 和 l2 当前节点的不断比较,当然,这里的当前节点是需要不断变化的。

2. 找变化:聚焦于某一个子问题,查看变化的量,通常会作为参数,这时可定义函数体。

由于当前节点的比较是不断变化的,所以这里变化的量我们就需要分情况讨论了,如下图,可总结为小的往前走一步,继续跟大的比

总结完情况,则进行代码实现:

public ListNode mergeTwoLists (ListNode listNode1, ListNode listNode2) {
     if(listNode1.val < listNode2.val){
         listNode1.next = mergeTwoLists(listNode1.next,listNode2);
         return  listNode1;
     }else {
         listNode2.next = mergeTwoLists(listNode1,listNode2.next);
         return  listNode2;
     }
 }

3. 找出口: 也就是找终止条件。

什么时候无法比较当前节点的值,这个比较好找,就是当 listNode1 的为 null,或者 listNode2 为 null 时,无法进行比较了,可直接返回对应有值的节点,代码如下。

 public ListNode mergeTwoLists (ListNode listNode1, ListNode listNode2) {
    if (listNode1 == null) {
        return listNode2;
    } else if (listNode2 == null) {
        return listNode1;
    } else if (listNode1.val < listNode2.val) {
        listNode1.next = mergeTwoLists(listNode1.next, listNode2);
        return listNode1;
    } else {
        listNode2.next = mergeTwoLists(listNode1, listNode2.next);
        return listNode2;
    }
}

1.2 复杂度分析

时间复杂度 O(m+n),m、n 分别为链表的长度,因为每次调用递归都会去掉 listNode1 或者 listNode2 的头节点(直到至少有一个链表为空),则最多只会递归调用每个节点一次。因此,时间复杂度取决于合并后的链表长度,即 O(m+n)。
空间复杂度 O(m+n),m、n 分别为链表的长度,递归需要消耗栈空间且大小取决于递归调用的深度。结束递归调用时最多调用 m+n 次,因此空间复杂度为 O(m+n)。

2. 迭代

2.1 解题思路

迭代与递归基本都是可以互转的,与递归类似,我们将两个链表的比较理解为指针的移动。

这里我们还需要一个哨兵节点,为什么需要哨兵节点呢,我们在遍历链表的过程中是不断的调整它的 next 指针,当我们遍历到最后时,哨兵节点更容易返回合并后的链表,过程如下图。

通过图解,可以了解迭代的大致流程,但是我们在 Java 代码实现时,还需要维护一个 prev 指针,用来调整它的 next 指针。

为什么需要这个指针而不是直接返回哨兵节点呢?原因是我们在不断的遍历中,指针会不断的下移,当我们合并完成所有的节点时,此时的指针是在最后,这时我们在获取合并后的链表就比较麻烦了。

而用一个 prev 指针代替哨兵节点去进行 next 指针的移动,当返回链表时,只需返回哨兵节点的 next 即可。

代码实现如下:

public ListNode mergeTwoLists(ListNode list1, ListNode list2) {
    
    // 哨兵节点的设置
    ListNode prehead = new ListNode(-1);

    // 维护 prev 指针进行移动
    ListNode prev = prehead;

    
    while (list1 != null && list2 != null) {
        // 值比较,小的接入哨兵节点,并往前走一步,继续与大的比较
        if (list1.val < list2.val) {
            prev.next = list1;
            list1 = list1.next;
        }
        else {
            prev.next = list2;
            list2 = list2.next;
        }
        
        // 指针移动到 next,为了后续的节点接入
        prev = prev.next;
    }

    // 三元运算,当 list1 或 list2 出现 null 时,非 null 的则可以直接接入哨兵节点
    prev.next = list1 != null ? list1 : list2;
    return prehead.next;
}

2.2 复杂度分析

时间复杂度 O(m+n),m、n 分别为链表的长度,合并操作只需遍历链表。
空间复杂度 O(1),prehead、prev 均只使用常数大小的内存空间。

标签:ListNode,21,next,链表,有序,listNode1,节点,listNode2
From: https://www.cnblogs.com/fuxing/p/18245251

相关文章

  • 洛谷 P1219 八皇后
    题目链接:八皇后思路    这是一个典型的搜索题目,从前往后依次枚举行数,从第一行开始依次枚举皇后的纵坐标,并判断当前坐标是否满足题目要求,满足题目要求则标记将答案存储,并继续向下枚举下一行。由分析可得每条对角线上的任意一点的横纵坐标满足公式i-j+n的值与对角......
  • 零基础非科班也能掌握的C语言知识21 编译链接(介于作者实力有限并且没有可以演示的过程
    编译链接1.翻译环境和运行环境2.翻译环境2.1编译2.1.1预处理(预编译)2.1.2编译2.1.3汇编2.2链接3.运行环境1.翻译环境和运行环境在ANSIC的任何⼀种实现中,存在两个不同的环境。编译环境运行环境2.翻译环境翻译环境由编译和链接两个大的过程组成的,而编译又可......
  • Linux Mint 21.3简介
    LinuxMint21.3是一个更新版本,其中包含了许多新特性和改进。以下是一些主要更新内容:1.Cinnamon6.0桌面环境:LinuxMint21.3采用了最新的Cinnamon6.0桌面环境,带来了新的功能和改进,例如支持Wayland会话(尽管仍处于实验性阶段)、改进的声音和电源小部件、对AVIF图像格式的新支......
  • [SWPUCTF 2021 新生赛]简简单单的逻辑
    查看源代码,大概意思就是已知result反推flagflag='xxxxxxxxxxxxxxxxxx'list=[47,138,127,57,117,188,51,143,17,84,42,135,76,105,28,169,25]result=''foriinrange(len(list)):key=(list[i]>>4)+((list[i]&0xf)<<......
  • 2024.05.21
    今日学习时长:83分钟;代码行数:41行博客数量:1篇今天主要开始了数据库实验三的操作,今天的大部分时长都在研究SQLserver数据库中的用户的新建和权限修改。SQLsever中直接用windows验证登录后可以在安全性—>登录名下新建一个用户,但是在切换为用户名+密码登录后,我发现我无法打开查......
  • 数据分享 I 1970-2021年各区县碳排放总量
    基本信息.数据名称:  1970-2021年各区县碳排放总量数据格式: Shp+excel数据几何类型: 面数据坐标系:  WGS84数据来源:网络公开数据......
  • 力扣面试题 02.07. 链表相交
    一 题目:二思路:本题介绍两种思路解题,个人推荐思路一快速好理解 思路一: 1.先把其中一个链表的值变成负数 2.遍历另一个链表第一个出现负数的值就是交点 3.还原被改的链表 思路二:1.先用第一个链表的头节点head1搜索指针q遍历第一个链表直到为空,再把q放到head2......
  • 计算机毕业设计项目推荐,32127 爬虫-自驾游搜索系统(开题答辩+程序定制+全套文案 )上万套
    目 录摘要1绪论1.1研究背景1.2爬虫技术1.3flask框架介绍21.4论文结构与章节安排32 自驾游搜索系统分析42.1可行性分析42.2系统流程分析42.2.1数据增加流程52.3.2数据修改流程52.3.3数据删除流程52.3系统功能分析52.3.1功能性分析62.......
  • FL Studio21.2.6破解中文版永久免费安装包网盘下载
    音乐制作爱好者们!你们是否曾经为了追求更好的音乐效果而苦恼?是否曾经因为正版FLStudio21的价格过高而望而却步?别担心,今天我为大家推荐一款破解中文版的FLStudio21,让你在不违法的前提下,以更低的成本获得专业音乐制作软件,实现你的音乐梦想!......
  • 代码随想录算法训练营第第35天 | 977.有序数组的平方1005.K次取反后最大化的数组和 、
    1005.K次取反后最大化的数组和本题简单一些,估计大家不用想着贪心,用自己直觉也会有思路。https://programmercarl.com/1005.K次取反后最大化的数组和.html自己写的时间复杂度太高,看答案优化/***@param{number[]}nums*@param{number}k*@return{number}*/varl......