从合并链表聊递归

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

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

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

  1. 将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
  2. 示例:
  3. 输入:1->2->4, 1->3->4
  4. 输出:1->1->2->3->4->4
  5. 来源:力扣(LeetCode

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

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

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

用伪代码写法就是:

  1. if l1.val < l2.val:
  2. l1.next = mergeTwoList(l1.next, l2)
  3. return l1
  4. else:
  5. l2.next = mergeTwoList(l1, l2.next)
  6. return l2

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

  1. if l1 === null:
  2. return l2
  3. if l2 === null:
  4. return l1

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

  1. type ListNode struct {
  2. Val int
  3. Next *ListNode
  4. }
  5. func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
  6. if l1 == nil {
  7. return l2
  8. }
  9. if l2 == nil {
  10. return l1
  11. }
  12. if l1.Val < l2.Val {
  13. l1.Next = mergeTwoLists(l1.Next, l2)
  14. return l1
  15. } else {
  16. l2.Next = mergeTwoLists(l1, l2.Next)
  17. return l2
  18. }
  19. }

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

  1. 执行结果:
  2. 通过
  3. 显示详情
  4. 执行用时:
  5. 0 ms
  6. , 在所有 Go 提交中击败了
  7. 100.00%
  8. 的用户
  9. 内存消耗:
  10. 2.6 MB
  11. , 在所有 Go 提交中击败了
  12. 63.64%
  13. 的用户

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

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

  1. func mergeTwoLists(l1 *ListNode, l2 *ListNode) *ListNode {
  2. head := &ListNode{}
  3. result := head
  4. for l1 != nil && l2 != nil {
  5. if l1.Val < l2.Val {
  6. head.Next = l1
  7. head = head.Next
  8. l1 = l1.Next
  9. } else {
  10. head.Next = l2
  11. head = head.Next
  12. l2 = l2.Next
  13. }
  14. }
  15. if l1 == nil {
  16. head.Next = l2
  17. }
  18. if l2 == nil {
  19. head.Next = l1
  20. }
  21. return result.Next
  22. }

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

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

  1. 执行用时:
  2. 4 ms
  3. , 在所有 Go 提交中击败了
  4. 62.28%
  5. 的用户
  6. 内存消耗:
  7. 2.5 MB
  8. , 在所有 Go 提交中击败了
  9. 100.00%
  10. 的用户

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

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. Java实现第九届蓝桥杯缩位求和

    缩位求和 题目描述 在电子计算机普及以前,人们经常用一个粗略的方法来验算四则运算是否正确. 比如:248 * 15 = 3720 把乘数和被乘数分别逐位求和,如果是多位数再逐位求和,直到是1位数,得 ...

  2. java实现第七届蓝桥杯平方末尾

    平方末尾 能够表示为某个整数的平方的数字称为"平方数" 比如,25,64 虽然无法立即说出某个数是平方数,但经常可以断定某个数不是平方数. 因为平方数的末位只可能是:[0, 1, ...

  3. c/c++混编

    /* head.h */#ifndef __SUM_H__ #define __SUM_H__ #ifdef __cplusplus extern "C" { #endif int ...

  4. KVM Web管理平台 WebVirtMgr

    WebVirtMgr介绍 WebVirtMgr是一个KVM管理平台,让kvm管理变得更为可视化,对中小型kvm应用场景带来了更多方便.WebVirtMgr采用几乎纯Python开发,其前端是基于Pyt ...

  5. ModelAndView的部分回顾

    ModelAndView的部分回顾 //@RestController @Controller //@SessionAttributes("user") //把modelandvi ...

  6. elementUI+国际化

    1. 先创建一个lang 文件夹,创建两个js文件en.js(英文), zh.js(中文), 另外创建一个index.js文件(用于) en.js zh.js (两者必须保持一致) 2. 在index ...

  7. 基于 abp vNext 和 .NET Core 开发博客项目 - Blazor 实战系列(四)

    系列文章 基于 abp vNext 和 .NET Core 开发博客项目 - 使用 abp cli 搭建项目 基于 abp vNext 和 .NET Core 开发博客项目 - 给项目瘦身,让它跑起来 ...

  8. 设计一个简单的多线程(Fecit)_1

    D6高级编程,Fecit ,学习里面关于线程创建的一个例子.,按照那个例子做的,不过本人喜欢将线程实现部分作为单独的单元,主线程再调用它. unit Unit1; interface uses Win ...

  9. 2019-02-12 html的初步学习

    前两天看了下python的爬虫,后面的抓包模拟登录实在是难弄,于是暂时放弃,来学学前端知识QAQ <!DOCTYPE html>文档类型符合HTML5标准 <html lang=&q ...

  10. Tensorflow从0到1(4)之神经网络

    一维数据集上的神经网络 # 1 引入包,创建会话 import tensorflow as tf import numpy as np sess = tf.Session() # 2 初始化数据 da ...