LeetCode 104 二叉树的最大深度
题目链接:104. 二叉树的最大深度 - 力扣(Leetcode)
昨天做用层序遍历的方法做过这道题,尝试用递归法:
# 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:
# 递归 后序遍历,获得节点左右子树的最大深度后加上当前节点的深度返回
def recur(node):
if not node:
return 0
left = recur(node.left)
right = recur(node.right)
return max(left, right) + 1
res = recur(root)
return res
做题时并没有区分深度和高度这两个概念,看了讲解发现自己对这两个的区别并不是很清晰,直观上就觉得应该用后序遍历:“二叉树节点的深度指从根节点到该节点的最长简单路径边的条数或者节点数(取决于深度从0开始还是从1开始);二叉树节点的高度指从该节点到叶子节点的最长简单路径边的条数或者节点数(取决于高度从0开始还是从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
from collections import deque
class Solution:
def maxDepth(self, root: Optional[TreeNode]) -> int:
# 递归 前序遍历
if not root:
return 0
def recur(node, result, depth):
result = max(result, depth)
if not node.left and not node.right:
return result # 遇到叶节点返回
if node.left:
result = max(result, recur(node.left, result, depth + 1))
# 回溯隐藏在depth + 1中(因为depth实际上并没有做+1, 而只是传入函数结果+1)
if node.right:
result = max(result, recur(node.right, result, depth + 1))
return result
res = recur(root, 0, 1) # 初始根节点深度为1
return res
LeetCode 111 二叉树的最小深度
题目链接:111. 二叉树的最小深度 - 力扣(Leetcode)
同样昨天已经做过迭代法层序遍历求深度,今天用递归法做题。如果只是简单地将求最大深度的代码中的max改为min,遇到一些测试用例会出错,比如退化为单链表的二叉树(所有节点都只有某一边的子节点),最小深度应该是对叶子节点,而不应包含空节点。尝试在递归函数返回值中加入限制,只有当左右子树高度都大于0时才取min,否则应该取max:
# 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 minDepth(self, root: Optional[TreeNode]) -> int:
# 递归 后序遍历,获得节点左右子树的最大深度后加上当前节点的深度返回
def recur(node):
if not node:
return 0
left = recur(node.left)
right = recur(node.right)
return min(left, right) + 1 if left !=0 and right != 0 else max(left, right) + 1
res = recur(root)
return res
本质上,max做的就是代码随想录讲解中分情况讨论的部分。
LeetCode 222 完全二叉树的节点个数
题目链接:222. 完全二叉树的节点个数 - 力扣(Leetcode)
使用二叉树任意一种遍历方式都可以完成在遍历过程中计数:
# 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 countNodes(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
# 递归 前序遍历
def dfs(node, count):
if not node:
return count
count += 1 # 中
count = dfs(node.left, count)
count = dfs(node.right, count)
return count
return dfs(root, 0)
利用完全二叉树的性质,需要知道如何判断以当前节点为根的子树是否为满二叉树:分别统计一直向左和一直向右的最大深度,如果二者相等,说明是满二叉树(完全二叉树特有的性质)。满二叉树的节点数量可直接由公式求得,否则继续递归当前节点的左右子树:
# 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 countNodes(self, root: Optional[TreeNode]) -> int:
# 利用满二叉树的性质
def dfs(node):
if not node:
return 0
left, right = node.left, node.right
l_depth, r_depth = 0, 0
while left:
l_depth += 1
left = left.left
while right:
r_depth += 1
right = right.right
if l_depth == r_depth:
return (2 << l_depth) - 1
return dfs(node.left) + dfs(node.right) + 1
return dfs(root)
N叉树求最大深度和节点数的原理和二叉树相同,只需把左右子节点的代码逻辑改为遍历节点的所有子节点,就不再具体列出。