算法刷题打卡015 | 二叉树相关题目3道

LeetCode 110 平衡二叉树

题目链接:110. 平衡二叉树 - 力扣(Leetcode)

平衡二叉树主要需要判断其所有子树是否都是高度差不大于1,第一次接触时不知道如何确定递归的返回值,后序遍历时既需要知道左右子树的高度,又需要知道左右子树各自是否平衡。讲解中比较巧妙的做法是返回一个固定值(比如高度不会为负数,可以使用-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
class Solution:
    def getDepth(self, node):
        if not node:
            return 0
        leftDepth = self.getDepth(node.left)
        rightDepth = self.getDepth(node.right)
        if leftDepth == -1 or rightDepth == -1:
            return -1  # 当有子树不平衡时,整棵树都不平衡
        if abs(leftDepth - rightDepth) > 1:
            return -1  # 以当前node为根的子树不平衡
        else:
            return 1 + max(leftDepth, rightDepth)  # 平衡时返回node的高度
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        if self.getDepth(root) == -1:
            return False
        else:
            return True

 代码实现要注意需要先判断左右子树各自是否平衡,而不是先判断左右子树返回值的差值,否则当左右返回值均为-1时容易出错。

LeetCode 257 二叉树所有路径

题目链接:257. 二叉树的所有路径 - 力扣(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 binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        res = []
        if not root:
            return res
        path = []
        def dfs(node):
            if not node:
                return
            # 把当前遍历到的节点加入路径
            path.append(str(node.val))
            path.append('->')
            # 依次遍历左子树和右子树
            dfs(node.left)
            dfs(node.right)
            if not node.left and not node.right:
                # 遍历到了叶子节点
                res.append(''.join(path[:-1]))
            # 回溯
            path.pop()  # pop '->'
            path.pop()  # pop node.val
            return
            
        dfs(root)
        return res

 二刷重新梳理思路和代码逻辑之后:

# # 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 binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        if not root:
            return []
        res, path = [], []
        def dfs(node):
            if not node:
                return
            # 把当前遍历到的节点加入路径
            path.append(str(node.val) + '->')
            if not node.left and not node.right:
                # 遍历到了叶子节点
                res.append(''.join(path)[:-2])
                path.pop()  # 别忘了这里也需要回溯
                return
            # 依次遍历左子树和右子树
            dfs(node.left)
            dfs(node.right)
            path.pop()  # pop回溯  node.val + '->'
            return
            
        dfs(root)
        return res

 看了讲解发现,做法一之所以不对是缺少了一次回溯(相当于收集结果以后没有把最近一次加入路径的叶节点回溯掉,它就会出现在其他路径中),做法二提交没问题,因为代码实现的差异,回溯的位置可能与一般做法不太一样。总的来说也算是做了两次回溯。

LeetCode 404 左叶子之和

题目链接:404. 左叶子之和 - 力扣(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 sumOfLeftLeaves(self, root: TreeNode) -> int:
        if not root: 
            return 0
        
        left_left_leaves_sum = self.sumOfLeftLeaves(root.left)  # 左
        right_left_leaves_sum = self.sumOfLeftLeaves(root.right) # 右
        
        cur_left_leaf_val = 0
        if root.left and not root.left.left and not root.left.right: 
            cur_left_leaf_val = root.left.val 
            
        return cur_left_leaf_val + left_left_leaves_sum + right_left_leaves_sum # 中

今天有点忙,暂时先做到这,周末有时间会来再看看。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值