• Golang从合并链表聊递归


    从合并链表聊递归

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

    最著名的例子就是斐波那契数列(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%
    的用户
    

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

  • 相关阅读:
    将帅问题
    堆栈(链栈)
    堆栈(基础实现原理 顺序栈)
    双向链表
    冒泡排序 (泛型版)
    maven
    jboss数据源配置
    仓库介绍,nexus的安装
    mave聚合继承
    mac mysql 安装
  • 原文地址:https://www.cnblogs.com/freephp/p/13251822.html
Copyright © 2020-2023  润新知