递归回溯本质

  1. 当前计算结果
  2. return :能向上汇报的
题目 当前计算的结果(更新全局/判断) return 向上汇报的内容
124. 最大路径和 左贡献 + 右贡献 + node.val max(左, 右) + node.val
543. 二叉树直径 左深度 + 右深度 max(左, 右) + 1
110. 平衡二叉树 abs(左高度 - 右高度) <= 1 max(左, 右) + 1
101. 对称二叉树 左边的左 vs 右边的右;左边的右 vs 右边的左 只有当 (当前两点值相等) (左边汇报是对称的) (右边汇报也是对称的) 时,才向上传递 True
200. 岛屿数量 判定当前节点是不是岛屿 不需要(只要把相连的"涂掉"即可)

  1. 最大路径和
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

        

  1. 二叉树直径
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
        

  1. 平衡二叉树
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

                 

  1. 对称二叉树
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)

  1. 岛屿数量

不能在 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
相关推荐
好学且牛逼的马2 小时前
【Hot100|25-LeetCode 142. 环形链表 II - 完整解法详解】
算法·leetcode·链表
样例过了就是过了4 小时前
LeetCode热题100 和为 K 的子数组
数据结构·算法·leetcode
Frostnova丶4 小时前
LeetCode 67. 二进制求和
算法·leetcode
昌兵鼠鼠4 小时前
LeetCode Hot100 哈希
学习·算法·leetcode·哈希算法
脏脏a4 小时前
【优选算法・双指针】以 O (n) 复杂度重构数组操作:从暴力遍历到线性高效的范式跃迁
算法·leetcode·双指针·牛客·优选算法
kamisama_zhu5 小时前
LeetCode 热题100快速通关指南(附模板) (优化完整版,真人心得版,持续更新)
算法·leetcode·职场和发展
蒟蒻小袁6 小时前
力扣hot-100(一刷自用版)
leetcode·哈希算法·散列表
踩坑记录7 小时前
leetcode ho100 124. 二叉树中的最大路径和 hard
leetcode
楠秋9207 小时前
代码随想录算法训练营第三十一天|56. 合并区间 、 738.单调递增的数字、968.监控二叉树
数据结构·算法·leetcode·贪心算法