二叉树递归学习笔记(二):相同的树,对称二叉树,平衡二叉树,二叉树的右视图

学习路线参考:如何灵活运用递归?【基础算法精讲 10】_哔哩哔哩_bilibili

ps:笔记和代码按本人理解整理,重思路

【如果笔记对你有帮助,欢迎关注&点赞&收藏,收到正反馈会加快更新!谢谢支持!】

上期笔记

二叉树递归学习笔记:最大深度&最小深度,路径总和-CSDN博客

题目1:相同的树

100. 相同的树 - 力扣(LeetCode)

  • 思路:比对两个树的对应递归单元是否相同
  • 拆解:
    • 递归单元:当前节点 & 左子树 & 右子树
    • 相同的两个树需要满足的条件:
      1. 当前节点的值相同 【p.val == q.val】
      2. 左子树相同【isSameTree(p.left, q.left) == True】
      3. 右子树相同【isSameTree(p.right, q.right) == True】
    • 递归终止:两个树有一个为None就终止(此时就可以知道True/False的结果了)
      • 都为None → True
      • 只有一个为None → False
  • 代码:
    class Solution:
        def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
            if p == None and q == None:  # 都为None
                return True
            elif p == None or q == None: # 只有一个为None
                return False
            else:  
                return p.val == q.val and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

题目2:对称二叉树

101. 对称二叉树 - 力扣(LeetCode)

  • 思路:对称二叉树(= 左子树和右子树对称)  → 转化为类似“相同的树”问题
  • 拆解:
    • 相同 → 对称 
      • 当前节点的值相同 【p.val == q.val】(不变)
      • 左子树相同【比较p.left, q.left】 → p的树和q的树相同【比较p.left, q.right
      • 右子树相同【比较p.right, q.right】 → p的树和q的树相同【比较p.right, q.left
  • 代码:
    class Solution:
        def isSymmetric(self, root: Optional[TreeNode]) -> bool:
            return self.isSameTree(root.left, root.right)
        
        def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
            if p == None and q == None:
                return True
            elif p == None or q == None:
                return False
            else:
                # 变化:比较“p.left & q.right” 和 "p.right & q.left"
                return p.val == q.val and self.isSameTree(p.left, q.right) and self.isSameTree(p.right, q.left)
    

     

题目3:平衡二叉树

110. 平衡二叉树 - 力扣(LeetCode)

  • 难点:递归要传递什么结果(计算是否平衡需要树的高度;但如果子树已经不平衡了,返回高度信息没有意义)
  • 拆解:
    • 不平衡条件:|左子树高度 - 右子树高度|> 1
    • 每个递归单元要判断:当前的树是否平衡
    • 每个递归单元要传递
      • 如果左右子树都平衡:当前树的高度【 max(左子树高度,右子树高度) + 1】
      • 任意一个子树不平衡:当前树不平衡的信号【如:-1】
    • 二叉树中任意一个子树不平衡,则整棵树就不平衡
    • 最后判断是否是平衡二叉树:如返回值是-1,则不平衡;返回值是高度,则平衡
  • 代码:
    class Solution:
        def isBalanced(self, root: Optional[TreeNode]) -> bool: 
            def dfs(root):
                if not root:
                    return 0
                left_height = dfs(root.left)
                right_height = dfs(root.right)
    
                # 有任意一个子树不平衡,则整棵树不平衡
                if left_height == -1 or right_height == -1: return -1
    
                # 如果子树平衡,判断当前的树是否平衡(决定返回高度,还是不平衡信号-1)
                if abs(left_height - right_height) >= 2: return -1
                else:
                    return 1+max(left_height, right_height)
            
            result = dfs(root)
            return result != -1
    

题目4:二叉树的右视图

199. 二叉树的右视图 - 力扣(LeetCode)

  • 难点:如何通过递归确定树的每个深度的最右节点?
    • ps:【深度和高度】对同一个二叉树来说,深度和高度相同;但对于这个树上的某个节点,深度为从上往下算(root为0),高度为从下往上算(叶子为0)
  • 拆解:
    • 二叉树的每个深度一定会有一个值 →  输出结果长度 == 树的深度
    • 递归顺序:先左后右【对每个树来说,先经过左子树的所有节点,再到右子树】
    • 对同一个深度,“后遇到(右侧节点)的值” 覆盖 “先遇到(左侧节点)的值”
  • 代码:
    class Solution:
        def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
            result = []
            def dfs(root, height):
                if not root: return 
    
                if height >= len(result):  # 第一次遇到当前深度
                    result.append(root.val)
                else:         # 覆盖同样深度左侧的节点
                    result[height] = root.val
    
                dfs(root.left, height+1)
                dfs(root.right, height+1)
    
            dfs(root, 0)
            return result

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值