解决这个问题可以用自顶向下(top-down),自底向上(bottom-up)两种解法
自顶向下的思路:
-
和前序遍历紧密关联(根->左->右)
-
当前节点的情况依赖于其父节点的情况
-
考虑完父节点,再考虑当前节点
每次向下递归,depth+1,设置self.ans=depth,并且不断比较更新这个值,得到最大深度
class Solution:
#自顶向下
def dfs(self,node,depth):
self.ans =max(depth,self.ans)
#递归终止条件
if node is None:
return
self.dfs(node.left,depth+1)
self.dfs(node.right,depth+1)
def maxDepth(self, root: Optional[TreeNode]) -> int:
self.ans=0
#递归入口
self.dfs(root,0)
return self.ans
自底向上的思路:
-
和后序遍历紧密关联(左->右->根)
-
当前节点的情况依赖于其所有子节点的情况
-
考虑完所有子节点,再考虑当前节点
如图,我们把最底下的叶节点深度看成1,那么节点3深度我们可以有预见性地看成2,节点1的根节点深度看成3.
节点3,为4,5的根节点,所以节点3的深度为左右子子树深度中的较大值加1:depth=max(left.depth,right.depth)+1
class Solution:
#自底向上
def dfs(self,node):
#递归终止
if node is None:
return 0
#递归子问题
left_depth =self.dfs(node.left)
right_depth=self.dfs(node.right)
return max(left_depth,right_depth)+1
def maxDepth(self, root: Optional[TreeNode]) -> int:
#递归入口
return self.dfs(root)
自顶向下:和前序遍历紧密关联(根->左->右)
自顶向下本质上是前序的深度搜索
前序:考虑当前节点在递归之前
#LeetCode144、二叉树的前序遍历
class Solution:
def dfs(self,ans,node):
if node is None:
return
ans.append(node.val)
self.dfs(ans,node.left)
self.dfs(ans,node.right)
#访问根的值->对左做递归->对右做递归
class Solution:
#自顶向下
def dfs(self,node,depth):
#更新高度
self.ans =max(depth,self.ans)
#递归终止条件
if node is None:
return
self.dfs(node.left,depth+1)
self.dfs(node.right,depth+1)
#更新高度->调用递归(左节点递归->右结点递归)
自底向上的思路:和后序遍历紧密关联(左->右->根)
自底向上本质上是后续的深度搜索,
后序:考虑当前节点在递归之后
#LeetCode145、二叉树的后序遍历
class Solution:
def dfs(self,ans,node):
if node is None:
return
self.dfs(ans,node.left)
self.dfs(ans,node.right)
ans.append(node.val)
#对左做递归->对右做递归->访问根结点
class Solution:
#自底向上
def dfs(self,node):
#递归终止
if node is None:
return 0
#递归子问题
left_depth =self.dfs(node.left)
right_depth=self.dfs(node.right)
return max(left_depth,right_depth)+1
调用递归(左节点递归->右结点递归)->#更新高度
这样的关联决定了代码结构;
class Solution:
#自顶向下
# def dfs(self,node):
# if node is None:
# return
# node.left,node.right =node.right,node.left
# self.dfs(node.left)
# self.dfs(node.right)
# def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
# self.dfs(root)
# return root
#自底向上
def dfs(self,node):
if node is None:
return
self.dfs(node.left)
self.dfs(node.right)
node.left,node.right = node.right,node.left
def invertTree(self, root: Optional[TreeNode]) -> Optional[TreeNode]:
self.dfs(root)
return root
#对于根节点的操作顺序决定了自顶向下/自底向上
class Solution:
# 自顶向下
def dfs(self,node,depth):
#递归终止条件:找到叶子节点,更新答案
if node.left is None and node.right is None:
self.ans = min(self.ans,depth)
return
#递归子问题
#若左节点存在,对其进行递归,深度+1
if node.left:
self.dfs(node.left,depth +1)
#若右节点存在,对其进行递归,深度+1
if node.right:
self.dfs(node.right,depth+1)
def minDepth(self, root: Optional[TreeNode]) -> int:
if root is None:
return 0
self.ans =inf
self.dfs(root,1)
return self.ans
class Solution:
def dfs(self,node,pathSum,targetSum):
if node is None:
return
pathSum += node.val
#递归终止
if node.left is None and node.right is None and targetSum == pathSum:
self.ans = True
return
self.dfs(node.left,pathSum,targetSum)
self.dfs(node.right,pathSum,targetSum)
def hasPathSum(self, root: Optional[TreeNode], targetSum: int) -> bool:
if root is None:
return False
self.ans =False
self.dfs(root,0,targetSum)
return self.ans