递归返回值的问题
问题一:
在翻转二叉树Leetcode226的问题中,递归的写法让我有一个疑问:
既然递归函数func invertTree(root *TreeNode) *TreeNode 是有返回值的,返回的是上一层的根节点。
既然有返回值,在递归函数中调用 invertTree 函数时,为什么没有用一个变量去接住返回值呢?(第7行为什么不是这么写的 变量 =invertTree(root.Left) )
第1行 func invertTree(root *TreeNode) *TreeNode {
第2行 if root == nil {
第3行 return nil
第4行 }
第5行 root.Left, root.Right = root.Right, root.Left //交换
第6行
第7行 invertTree(root.Left)
第8行 invertTree(root.Right)
第9行
第10行 return root
}
问题二:
递归函数什么时候需要有返回值?如果有返回值的时候,在递归函数中调用递归函数的时候,在这种情况下什么时候需要用变量去接返回值。
正在回答 回答被采纳积分+1
这个问题没有返回值确实可以,设立返回值完全是问题本身给定的函数定义中包含了返回值。
==========
关于递归函数何时有返回值,何时没有返回值,完全是根据逻辑走的,你设计的逻辑需要有返回值,就要有返回值;可以不要返回值,就可以不设定返回值。
这个回答跟没回答一样,但事实就是如此。我无法给出一个“规定”,你把这个规定记住了,从此递归函数的设计就没有问题了。这也是我在这个课程中一直强调的,算法不是背出来的,一定要想明白逻辑。逻辑想清楚了,一个算法可以有很多种实现方式,而不是只有一种一成不变的模板。
这本身也是我们学习算法和数据结构的主要目的。大多数算法和数据结构我们不需要从底层实现,我们通过学习他们,加深我们对计算机逻辑执行和设计的理解,在需要的时候设计属于我们自己的逻辑。
==========
另外值得一提的是,对树或者链表的操作,返回相应的根节点和头结点,属于一个 best practice。注意,不是 correct practice,而是 best practice。比如对于这个问题,你不返回根节点,也能设计出正确的逻辑,但是返回根节点,更符合大多数人的预期。这样别人在使用相应的树操作或者链表操作的时候,不需要查询这个函数到底有返回值还是没有返回值,都有返回值就好了。需要用就用,不需要用,也没有影响。
这样的例子很多,比如对于机器学习算法的设计,一个 best pratice 就是所有的算法都走 fit -> predict 的 pipeline。尽管有一些算法没有 fit 的过程,但我们也写一个空的 fit,这样屏蔽掉外部调用的不一致性。每一个算法从外部看,都在走同样的流程。
继续加油!:)
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星