合并两个链表c++_合并两个链表递归版

本文详述了使用递归方法合并两个已排序链表的过程,包括终止条件和每一步的操作,并通过图解展示了递归调用和返回的详细步骤。
摘要由CSDN通过智能技术生成

递归版题解

这题曾经写过,原文点这里,之前对递归的图解有点简单。

这次把递归版本重新写了一下,着重于图解部分,将递归怎么一步步调用的,怎么一步步返回的详细画了一遍。

先来回顾下这道题目吧:
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4

递归的两个条件:

  1. 终止条件:当l1或者l2中有一个为空时,就返回
  2. 函数内要做什么:如果l1.val小于等于l2.val,那么将l1.next指向 l1的后续节点和l2中较小的一个

终止条件比较好理解,函数内做的事情就不那么好懂了 l1的后续节点和l2中较小的一个

如果是 l1.val<=l2.val,我们就能确定一个较小的节点了,也就是l1。因为链表还没结束,我们要继续比较,这时候比较的是l1.next和l2。

反之,如果是l1.val>l2.val,我们也能确定一个较小的节点,现在是l2.因为链表还没结束,我们继续比较,这时候比较的是l1和l2.next。

后面就是不断的递归,最终把整个链表给串起来。c9425f3f70bb8b0ce1979028c4b040f3.gif

java版本如下:

class Solution {
public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
//递归的结束条件,如果l1和l2中有一个为空就返回
if(l1==null || l2==null) {
return (l1==null)? l2:l1;
}
//如果l1的值<=l2的值,就继续递归,比较l1.next的值和l2的值
//l1.next和l2比较完后,会产生一个更小的节点x,将x加到当前l1的后面
if (l1.val<=l2.val) {
l1.next = mergeTwoLists(l1.next,l2);
return l1;
//如果l1的值>l2的值,就继续递归,比较l1的值和l2.next的值
} else {
l2.next = mergeTwoLists(l1,l2.next);
return l2;
}
}
}

python版本如下:

class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
#递归的结束点就是L1或者L2为空就返回
#如果L1为空就返回L2,L2为空返回L1
ifnot (l1 and l2):
return l1 if l1 else l2
#L1的val<=L2的val,那么继续递归
#当前L1的next指向一个递归函数
#意思是L1的下一个和L2哪个大,就作为当前L1的next
if l1.val<=l2.val:
l1.next = self.mergeTwoLists(l1.next,l2)
return l1
else:
l2.next = self.mergeTwoLists(l1,l2.next)
return l2

时间复杂度:O(n + m),其中 n 和 m 分别为两个链表的长度   

空间复杂度:O(n + m)

详解执行过程

我们定义两个链表:1->2->41->3->4
L1即为第一个链表,L2为第二个链表
两个链表下方是代码部分,具体如下图所示:f560b51166e64507eb804d8100a43181.png再解释一下上图中代码部分:

  • 第一个if:递归的终止条件,如果链表1为空 或者 链表2为空就返回
  • 第二个if:如果链表1的节点值 <= 链表2的节点值,则继续下一层的递归比较
  • else部分:如果链表1的节点值 > 链表2的节点值,则继续下一层递归比较

后面我们就开始不断比较,不断调用下一层递归函数
每一步中,具体执行到哪段代码,我用红色标记出来了:

635658346a54aa0d262490d90e0bf8be.png 5272cdfd24a31b5bda94baa581482cf5.png 054181fac19f60408d5704ee084b7ee9.png e6d188bd875ea784ff450ada153eea69.png 2467e71b91d35f0432d1f0503209fe0b.png 25505249affca80d58553481e36edbd8.png 4bc0842be4bcd12476e57cd8aa15fb93.png fa29ab5d4c5d88d6ff35175461199bb1.png dfc9978bd92d725ccfc78e53eb96d5f5.png 3576f3d18d46d2c3c14b560d2f104555.png

<<< 左右滑动见更多 >>>

  • 上图中第一步、第二步:当链表1的节点1 <= 链表2的节点1时候,让链表1的节点1.next指向下一层递归函数,但此时程序并没有执行完,链表1的节点1.next指向的还是一个未知的节点,到底会指向谁,需要等后面的递归函数执行完返回后才知道
  • 第三步、第四步:链表1的节点2>链表2的节点1,让链表2的节点1.next指向下一层递归函数,具体指向谁需要等后面的递归函数执行完返回后才知道
  • 第五步、第六步:链表1的节点2<=链表2的节点3,让链表1的节点2.next 指向下一层递归函数
  • 第七步、第八步:链表2的节点3.next 指向下一层的递归函数
  • 第九步、第十步:链表1的节点4.next 指向下一层递归函数

经过上面 10 步之后,递归调用就到头了,因为上图中最后一张图,最右边的黑色方框里只剩下一个4了。此时就会触发递归终止条件,然后不断返回

58606e92fadf7a1f8cc8b4ebfafc850a.png caa58504e9c5c1c5ebdbf95189127b11.png 0e20bff34f0dd459bf164602b38b1fde.png 8f89f2289b1a2a1bc9cc3015d3c7174f.png 8623149bdf74eb2f80f772eaca888ee5.png 617ab2c4323098b8856cc7462e8c4899.png 043150afcf6aea60ef448ecba4635faa.png 8729eb9f4c3578817bb48cd3f3c9ed30.png 43fd68022f974ae0797e50a4d693cbc8.png 1d06f2f78a785f9e3fe9cb013556bb42.png

<<< 左右滑动见更多 >>>

再来分析一下上图中递归函数是怎么返回的:

  • 第11步:此时链表1为空,于是触发递归终止条件,返回链表2的节点4
  • 第12步:链表2的节点4返回到上一层递归函数,上一层函数是链表1的节点4,于是链表1的节点4.next 就指向 链表2的节点4
  • 第13步:链表1的节点4返回
  • 第14步:链表2的节点4返回到上一层递归函数,上一层函数是链表2的节点3,于是链表2的节点3.next 就指向 链表1的节点4
  • 第15步:链表2的节点3返回
  • 第16步:链表2的节点3返回到上一层递归函数,上一层的函数是链表1的节点2,于是链表1的节点2.next 就指向 链表2的节点3
  • 第17步:链表1的节点2返回
  • 第18步:链表1的节点2返回到上一层递归函数,上一层函数是链表2的节点1,于是链表2的节点1.next 就指向 链表1的节点2
  • 第19步:链表2的节点1返回
  • 第20步:链表2的节点1返回到上一层递归函数,上一层函数是链表的节点1,于是链表1的节点1.next 就指向 链表2的节点1

如下图所示,最后返回链表1的节点1,此时两个链表就被合并成一个链表了c14177fde5da1e18d38de3c670b48b70.png

推荐阅读   点击标题可跳转

合并两个有序链表

反转链表

再谈反转链表递归版

合并K个排序链表

看完本文有收获?请转发分享给更多人

e7bb55c34e47b1f36b6fdf5c2d7bfc71.png

好文章,我在看❤️

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值