- 当前计算结果
- return :能向上汇报的
| 题目 | 当前计算的结果(更新全局/判断) | return 向上汇报的内容 |
|---|---|---|
| 124. 最大路径和 | 左贡献 + 右贡献 + node.val |
max(左, 右) + node.val |
| 543. 二叉树直径 | 左深度 + 右深度 |
max(左, 右) + 1 |
| 110. 平衡二叉树 | abs(左高度 - 右高度) <= 1 |
max(左, 右) + 1 |
| 101. 对称二叉树 | 左边的左 vs 右边的右;左边的右 vs 右边的左 | 只有当 (当前两点值相等) 且 (左边汇报是对称的) 且 (右边汇报也是对称的) 时,才向上传递 True |
| 200. 岛屿数量 | 判定当前节点是不是岛屿 | 不需要(只要把相连的"涂掉"即可) |
- 最大路径和
python
# 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 maxPathSum(self, root: Optional[TreeNode]) -> int: # 返回root的最大路径
# 全局变量记录遍历过程中产生的最大值。
self.max_sum = float('-inf') # 子函数需要调的父函数的变量self.
def dfs(node):
if not node: # 没有节点,和为 0
return 0
# 1. 向下递归:子树贡献是负数,不选
left_gain = max(dfs(node.left), 0) # 左子节点的最大路径
right_gain = max(dfs(node.right), 0) # 左子节点的最大路径
# 2. "拐弯"的路径: 左边贡献 + 当前节点 + 右边贡献
# 如果左右子树贡献为0,自然就是"单边"or"就node自己"
current_path_sum = node.val + left_gain + right_gain
# 更新全局最大值
self.max_sum = max(self.max_sum, current_path_sum)
# 3. 向上回溯:返回给父节点
# node作为父节点的子节点,(node向下只能单边)
return node.val + max(left_gain, right_gain)
dfs(root) # 在dfs中更新全局变量
return self.max_sum
- 二叉树直径
python
# 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 diameterOfBinaryTree(self, root: Optional[TreeNode]) -> int:
self.ans = 0 # 全局变量
def depth(node):
# 1. 出口:空节点高度为 0
if not node:
return 0
# 2. 递归:获取左右子树的高度
left = depth(node.left)
right = depth(node.right)
# 3. 操作:更新全局最大直径(左高度 + 右高度)(边的数量)
self.ans = max(self.ans, left + right)
# 返回当前节点的高度给上一层
return max(left, right) +1
depth(root) # 在dfs中更新全局变量
return self.ans
- 平衡二叉树
python
# 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
# 平衡二叉树 是指该树所有节点的左右子树的高度相差不超过 1。
class Solution:
def isBalanced(self, root: Optional[TreeNode]) -> bool:
self.res = True # 全局变量,默认是平衡的
def dfs(node):
if not node or not self.res: # 如果已经发现不平衡了,不再深挖
return 0
left_h = dfs(node.left)
right_h = dfs(node.right)
# 检查当前节点平不平衡
if abs(left_h - right_h) > 1:
self.res = False # 发现不平衡,修改全局变量
# 守规矩:向上汇报高度
return max(left_h, right_h) + 1
dfs(root) # dfs修改全局变量
return self.res
- 对称二叉树
python
class Solution:
def isSymmetric(self, root: Optional[TreeNode]) -> bool:
if not root:
return True
def check(L, R):
# 1. 终止条件(汇报最底层的真相)
if not L and not R: # 都为空,对称
return True
if not L or not R: # 其中一个为空,不对称
return False
if L.val != R.val: # 值不等,不对称
return False
# 2. 向下递归 + 向上汇报
# 此时办的"大事"是:同时检查"外侧"和"内侧"
# 外侧对称:L.left vs R.right
# 内侧对称:L.right vs R.left
return check(L.left, R.right) and check(L.right, R.left)
# 启动:传入根节点的左右子树开始对比
return check(root.left, root.right)
- 岛屿数量
不能在 dfs 内部 self.cnt += 1,这样最后统计出来的不是"岛屿的数量",而是所有陆地格子的总面积
python
class Solution:
def numIslands(self, grid: List[List[str]]) -> int:
if not grid:
return 0
m = len(grid)
n = len(grid[0])
# 递归函数dfs用于判别当前节点是不是陆地,并递归左右上下,不需要返回
def dfs(i,j):
# 停止搜索条件:出界、不是陆地
if i>=m or i<0 or j<0 or j>=n or grid[i][j] != '1':
return # 停止搜索
# 则 grid[i][j] == '1' 陆地,标记改陆地已搜索
grid[i][j] = '2'
# 递归 左右上下
dfs(i, j-1)
dfs(i, j+1)
dfs(i-1, j)
dfs(i+1, j)
count = 0
# 遍历每一个格子
for row in range(m):
for col in range(n):
if grid[row][col] == '1':
# 发现新岛屿!
count += 1
# 派 DFS 去把这座岛所有相连的陆地都标记了
dfs(row, col) # 只在发现陆地时,去搜索当前陆地周围
return count