LeetCode 二叉树递归方法
1.二叉树介绍
1.1 二叉树含义
树 是一种经常用到的数据结构,用来模拟具有树状结构性质的数据集合。
树里的每一个节点有一个值和一个包含所有子节点的列表。从图的观点来看,树也可视为一个拥有N 个节点和N-1
条边的一个有向无环图。二叉树是一种更为典型的树状结构。如它名字所描述的那样,二叉树是每个节点最多有两个子树的树结构,通常子树被称作“左子树”和“右子树”。
1.2 二叉树遍历方法
二叉树分别有前序遍历、中序遍历,后序遍历和层序遍历方式
- 前序遍历
前序遍历首先访问根节点,然后遍历左子树,最后遍历右子树。前序遍历的第一个值就是根节点的值。
- 中序遍历
先遍历左子树,然后访问根节点,然后遍历右子树。二叉树的根节点在遍历序列的中部,它的左侧都为左子树的节点,右侧都为右子树的节点。
- 后序遍历
先遍历左子树,然后遍历右子树,最后访问树的根节点。二叉树的根节点在遍历序列的最后位置。
前序遍历、中序遍历、后序遍历代表着是根节点遍历的顺序。前序遍历为根左右、中序遍历为左根右、后序遍历为左右中。
2. 二叉树的递归方法
2.1 递归三要素
递归算法能够很方便的应用在二叉树的问题上。应用递归方法首先要确定递归的三要素。
-
确定递归函数的参数和返回值:
确定哪些参数是递归的过程中需要处理的,那么就在递归函数里加上这个参数, 并且还要明确每次递归的返回值是什么进而确定递归函数的返回类型。 -
确定终止条件:
写完了递归算法, 运行的时候,经常会遇到栈溢出的错误,就是没写终止条件或者终止条件写的不对,操作系统也是用一个栈的结构来保存每一层递归的信息,如果递归没有终止,操作系统的内存栈必然就会溢出。 -
确定单层递归的逻辑:
确定每一层递归需要处理的信息。在这里也就会重复调用自己来实现递归的过程。
2.2 递归实现二叉树遍历
对于二叉树的递归方法而言,最重要的就是弄清楚当前根节点的具体操作,然后递归的调用子节点。
首先以前序遍历为例
class Solution(object):
def preorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if not root:
return []
res = [root.val]
res += self.preorderTraversal(root.left)
res += self.preorderTraversal(root.right)
return res
-
递归函数参数和返回值
利用递归实现二叉树的前序遍历,因此递归函数需要输入的是当前的根节点,从而生成该根节点下的前序遍历的结构。 -
递归函数终止条件
当根节点为None时,说明已经达到了最后节点,需要终止迭代。 -
单层递归的逻辑
由于是前序遍历,首先要把根节点的值添加进列表,然后再遍历左子树,最后遍历右子树。res = [root.val] # 将根节点的值添加进列表 res += self.preorderTraversal(root.left) # 递归遍历左子树 res += self.preorderTraversal(root.right) # 递归遍历右子树
同理,中序遍历和后序遍历的不同之处是根节点遍历的位置不同,所以只需要修改代码中根节点加入列表的位置即可。
中序遍历
class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if root is None:
return []
result = []
result += self.inorderTraversal(root.left) # 左子树
result.append(root.val) # 根节点
result += self.inorderTraversal(root.right) # 右子树
return result
后序遍历
class Solution(object):
def inorderTraversal(self, root):
"""
:type root: TreeNode
:rtype: List[int]
"""
if root is None:
return []
result = []
result += self.inorderTraversal(root.left) # 左子树
result.append(root.val) # 根节点
result += self.inorderTraversal(root.right) # 右子树
return result
3.案例分析
3.1 二叉树的最大深度
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树 [3,9,20,null,null,15,7],
最大深度为3
知道当前根节点root
的左子树的深度和右子树的深度,则根节点的最大深度为左子树和右子树两者之间的最大深度加1。
所以构造递归函数分别求取左子树和右子树的最大深度,然后在根节点比较两者的最大值然后加1作为返回值,记得到当前根节点root
的最大深度。
class Solution(object):
def maxDepth(self, root):
"""
:type root: TreeNode
:rtype: int
"""
if not root: # 节点为None, depth为0
return 0
left_depth = self.maxDepth(root.left) # 计算左子树的深度
right_depth = self.maxDepth(root.right) # 计算右子树的深度
return max(left_depth, right_depth) + 1
未完待续