从合并链表聊递归

递归是工程师最常见的一种解决问题的方式,但是有时候不容易真正掌握。有人说是看起来很简单,自己写起来会费点劲。

最著名的例子就是斐波那契数列(Fibonacci sequence),通过寻找递推公式来计算出结果。

而最近刷到的一道合并链表的算法题,也可以使用递归来实现。下面看看题目描述吧:

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

示例:

输入:1->2->4, 1->3->4
输出:1->1->2->3->4->4 来源:力扣(LeetCode)

先抛出本人观点,递归的关键是:找到边界条件递归公式

分析一下题目,可以发现用第一个链表l1的头部节点来去和l2的节点对比,如果大于l2的当前节点,那么偏移l1的next和l2继续对比大小。反之如果l1的头节点对比L2的当前节点更小,那么就需要对l2做类似处理。

这种不断对比和偏移的过程,可以总结出一种递归公式。

用伪代码写法就是:

if l1.val < l2.val:
l1.next = mergeTwoList(l1.next, l2) return l1
else:
l2.next = mergeTwoList(l1, l2.next)
return l2

而边界条件就是在不断偏移的时候,走到某个链表的最后一个节点为止,伪代码就是:

if l1 === null:
return l2 if l2 === null:
return l1

用golang来实现,代码也很清晰:

type ListNode struct {
Val int
Next *ListNode
} func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
if l1 == nil {
return l2
} if l2 == nil {
return l1
} if l1.Val < l2.Val {
l1.Next = mergeTwoLists(l1.Next, l2)
return l1
} else {
l2.Next = mergeTwoLists(l1, l2.Next)
return l2
}
}

在LeetCode里面提交,运行反馈如下:

执行结果:
通过
显示详情
执行用时:
0 ms
, 在所有 Go 提交中击败了
100.00%
的用户
内存消耗:
2.6 MB
, 在所有 Go 提交中击败了
63.64%
的用户

可以看到递归是非常消耗内存的,它循环调用,犹如尔罗斯套娃,一层一层返回内层的调用结果。

如果要优化的话可以使用迭代方式来实现,代码需要做一些调整:

func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
head := &ListNode{}
result := head
for l1 != nil && l2 != nil {
if l1.Val < l2.Val {
head.Next = l1
head = head.Next
l1 = l1.Next
} else {
head.Next = l2
head = head.Next
l2 = l2.Next
}
} if l1 == nil {
head.Next = l2
} if l2 == nil {
head.Next = l1
} return result.Next
}

可以看出需要创建一个头部指针来做偏移,而最终result作为一个合成结果链表来存储结果。

最后提交执行,发现结果数据稍微好看了一丢丢:

执行用时:
4 ms
, 在所有 Go 提交中击败了
62.28%
的用户
内存消耗:
2.5 MB
, 在所有 Go 提交中击败了
100.00%
的用户

由于在数据量不大的情况下,其实性能差距也不大,所以使用递归也是没有毛病的。

Golang从合并链表聊递归的更多相关文章

  1. [LeetCode题解]23. 合并K个升序链表 | 分治 + 递归

    方法一:分治 + 递归 解题思路 在21. 合并两个有序链表,我们知道如何合并两个有序链表.而本题是合并 k 个有序链表,可以通过大问题拆分成小问题解决,即把 k 个链表,拆分成 k/2 个链表组,俩 ...

  2. [算法]合并链表&删除数组重复项

    合并链表 题目 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出:1-> ...

  3. [剑指offer]25.合并两个排序的链表(迭代+递归)

    25.合并两个排序的链表 题目 输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的. 示例1: 输入:1->2->4, 1->3->4 输出:1-> ...

  4. 链表有环判断,快慢指针两种方法/合并链表/删除重复元素/二分递归和while

    public static boolean hasCycle(ListNode head) { if (head == null || head.next == null) { return fals ...

  5. 四、golang内置函数、递归、闭包、数组切片和map

    一.总体内容 1.内置函数.递归函数.闭包 2.数组和切片 3.map数据结构 4.package介绍 一.内置函数 注意:值类型用new来分配内存,引用类型用make来分配内存 1.close:主要 ...

  6. 链表list容器中通过splice合并链表与merge的不同,及需要注意的问题

    #include "stdafx.h" #include <iostream> #include <list> #include <algorithm ...

  7. c# 有序链表合并 链表反转

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  8. Java链表和递归

    删除链表的指定元素: public class ListNode { public int val; public ListNode next; public ListNode(int x){ val ...

  9. merge-two-sorted-lists合并链表

    Merge two sorted linked lists and return it as a new list. The new list should be made by splicing t ...

随机推荐

  1. pi-star镜像 下载地址

    Pi-Star_NanoPi_Air_V3.4.17_09-Jan-2019.zip nanopi air点这里  Pi-Star_NanoPi_V3.4.17_09-Jan-2019.zip nan ...

  2. 解决关闭app权限弹框后无法识别页面对象问题

    在使用appium进行安卓端app的自动化测试,我碰到这样下面这几个问题: 1.每次启动我的待测app时总会提示app权限 2.关闭完权限后,无法识别页面对象 第一个问题的解决,我更换不同的真机进行测 ...

  3. 信道估计(channel estimation)图解——从SISO到MIMO原理介绍

    1. 引言 在所有通信中,信号都会通过一个介质(称为信道),并且信号会失真,或者在信号通过信道时会向信号中添加各种噪声.正确解码接收到的信号而没有太多错误的方法是从接收到的信号中消除信道施加的失真和噪 ...

  4. ASP.NET Core 3.1 WebApi部署到腾讯云CentOS 7+Docker

    一.准备 首先需要有一台CentOS服务器,安装最新版Docker,配置镜像加速等,安装方法网上很多,下面是一些相关指令: yum install -y yum-utils device-mapper ...

  5. hibernate中的映射

    hibernate中的映射是指Java类和数据库表中的属性来进行关联,然后通过类来操作数据库中,这就是简单的映射.

  6. Spring杂谈 | 从桥接方法到JVM方法调用

    前言 之所以写这么一篇文章是因为在Spring中,经常会出现下面这种代码 // 判断是否是桥接方法,如果是的话就返回这个方法 BridgeMethodResolver.findBridgedMetho ...

  7. Windows环境下PHP安装pthreads多线程扩展

    一.判断PHP是ts还是nts版 通过phpinfo(); 查看其中的 Thread Safety 项,这个项目就是查看是否是线程安全,如果是:enabled,一般来说应该是ts版,否则是nts版. ...

  8. Nice Jquery Validator 自定义规则

    规则定义方式 (1). 正则 适用于使用单个正则能搞定的验证. // 使用数组包裹正则和错误消息,规则不通过时提示该消息 mobile: [/^1[3458]\d{9}$/, '请检查手机号格式'] ...

  9. FFT,NTT入门

    目录 -1.前置知识 复数 单位根 单位根反演 0.卷积 1.FFT -1.前置知识 复数   复数单位\(i\):定义为\(i^2=-1\).\(i\)可以直接参与运算.   复数:形如\(z=a+ ...

  10. Docker_01

    目录 1.1 Docker简介 1.1.1 为什么会有Docker的出现? 1.1.2 Docker理念 1.1.3 Docker or 虚拟机? 2.1 Docker安装 3.1 Docker基本使 ...