看完本节课你可以回答以下几个问题。
递归很重要,希望大家也能深入理解,不要碰到不会的直接放弃了。
放弃很容易,坚持很酷。
- 理解递归的思维方式。
- 为什么二叉树相关的题目可以使用递归来解决?
- 为什么需要使用递归?
- 为什么递归可以得到正确答案?
- 计算机是如何使用递归的?
- 写一个递归的套路有哪些?
递归是计算机中的很重要的思维方式,首先我们要理解递归的概念。
递归的基本思想是可以把某个问题拆解成更小的问题,如果把这些小问题解决了,大问题自然而然的解决了,不需要去考虑子问题是怎么解决的,但是我们知道最小的问题是怎么解决的。是一种纵向逐级解决的问题。
递归和循环在思维方式上是有区别的。
比如我们我们计算一个数组的和。 [1,2,3,4,5]。
- 递归的方式解决: 我们求sum(nums),我们需要计算 nums[-1] + sum(nums[:-1]) , 也就是说小问题是计算sum(nums[:-1]) ,但是我们知道最终的解决问题, sum(nums[0]) = nums[0], 只要递归解决就行了,是一种全局的解决问题的思维。
- 有一个终止条件。
- 可以把问题拆解成更小的问题或者性质一样的问题。
- for循环, 是用一个全局遍历,不断的去拿到这个值和全局变量相加。 本质上是一种迭代的思想。
那为什么递归是正确的, 这就是高中学的数学归纳法。
为什么二叉树是可以使用递归呢?
二叉树的结构和递归思维完全一致,左子树、右子树都是和整体二叉树是一个结构。
计算机是怎么计算递归的?
递归: 就是从全局开始,不断解决小问题,更小的问题..以至于到原子问题,(递)然后从原子问题开始向上反馈结果,直到把最终的问题解决完,返回最终的结果。(归),计算机中使用了栈的数据结构来保存和计算。
写递归有什么套路?
- 终止条件。
- 调用自己的计算过程。
下面从一道题理解递归的解法。
二棵树最大的深度是指从根节点到最远叶子节点的最长路径上的节点数,
- 终止条件: 当节点为空是,高度为0
- 计算逻辑: depth = max(left_depth, root_depth) + 1
代码
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root: return 0 #终止条件。
l_depth = self.maxDepth(root.left) # 相信你能计算出来左子树
r_depth = self.maxDepth(root.right) # 相信你能计算出来右子树
return max(l_depth, r_depth) + 1
另外一种解法
前一种思路是把节点传下去,这种思路可以个数传下去。
比如第一层的时候 1 传入到下层数中,分别去传到左子树和右子树中。如果节点不为空就继续往下传递。那叶子结点就是所有路径的节点数了。再维护一个全局变量,不断更新这个最大值就是结果了。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
ans = 0
def dfs(node, cnt):
if node is None: #终止条件了
return
cnt +=1
nonlocal ans
ans = max(ans, cnt)
dfs(node.left, cnt) # 左兄弟,我给你我的结果,你继续传递。
dfs(node.right, cnt) # 左兄弟,我给你我的结果,你继续传递。
dfs(root, 0)
return ans
系列文章