代码随想录算法训练营第十五天 | 110.平衡二叉树、257. 二叉树的所有路径、404.左叶子之和、222.完全二叉树的节点个数

一、110.平衡二叉树

题目链接:110. 平衡二叉树 - 力扣(LeetCode)
文章讲解:110.平衡二叉树 | 代码随想录 (programmercarl.com)
视频讲解:后序遍历求高度,高度判断是否平衡 | LeetCode:110.平衡二叉树_哔哩哔哩_bilibili

Carl说:再一次涉及到,什么是高度,什么是深度,可以巩固一下。

"""
错误代码,理解错误,不是比较最小深度和最大深度差是否小于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)
        depth = 1 + max(leftdepth, rightdepth)

        return depth

    # 获取最小深度
    def getheight(self, node):
        if not node:
            return 0

        leftheight = self.getheight(node.left)
        rightheight = self.getheight(node.right)

        # 左子树为空,右子树不为空,则高度为右子树高度+1
        if node.left == None and node.right != None:
            return 1 + rightheight
        
        # 左子树不为空,右子树为空,则高度为左子树高度+1
        if node.left != None and node.right == None:
            return 1 + leftheight
 
        # 左右子树均不为空,则高度为左右子树高度+1
        result = 1 + min(leftheight, rightheight)
        return result

    # 判断是否为平衡树
    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        error = self.getdepth(root) - self.getheight(root)
        if error <= 1:
            return True
        else:
            return False
"""
正确代码
"""
# 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:
    # 1. 确定递归函数的参数和返回值
    def getheigh(self, node):
        # 2. 确定终止条件
        if not node:
            return 0

        # 3. 确定单层递归的逻辑,后序遍历
        leftheight = self.getheigh(node.left)   # 左
        # 左子树不符合平衡二叉树条件
        if leftheight == -1:
            return -1
        
        rightheight = self.getheigh(node.right) # 右
        # 右子树不符合平衡二叉树条件
        if rightheight == -1:
            return -1

        # 左右子树都符合平衡二叉树,判断高度差
        if abs(leftheight - rightheight) > 1:   # 中
            return -1
        else:
            return 1 + max(leftheight, rightheight)


    def isBalanced(self, root: Optional[TreeNode]) -> bool:
        if self.getheigh(root) != -1:
            return True
        else:
            return False

二、257. 二叉树的所有路径

题目链接:257. 二叉树的所有路径 - 力扣(LeetCode)
文章讲解:257. 二叉树的所有路径 | 代码随想录 (programmercarl.com)
视频讲解:递归中带着回溯,你感受到了没?| LeetCode:257. 二叉树的所有路径_哔哩哔哩_bilibili

Carl说:这是大家第一次接触到回溯的过程, 我在视频里重点讲解了 本题为什么要有回溯,已经回溯的过程。 如果对回溯 似懂非懂,没关系, 可以先有个印象。

遍历顺序:前序遍历,因为需要父节点指向子节点,并将路径输出。

# 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:
    # 1. 确定递归函数的参数和返回值
    def traversal(self, node, path, result):
        # 中,把中值加入path中
        path.append(node.val)

        # 2. 确定终止条件,node左右子节点都为空
        if not node.left and not node.right:
            path_res = '->'.join(map(str, path))
            result.append(path_res)
            return

        # 左
        if node.left:
            self.traversal(node.left, path, result)
            path.pop()      # 回溯
        # 右
        if node.right:
            self.traversal(node.right, path, result)
            path.pop()      # 回溯


    def binaryTreePaths(self, root: Optional[TreeNode]) -> List[str]:
        # 1. 确定递归函数的参数和返回值
        result = []
        path = []

        # 2. 确定终止条件
        if not root:
            return result

        # 3. 确定单层递归的逻辑
        self.traversal(root, path, result)
        return result

三、404.左叶子之和

题目链接:404. 左叶子之和 - 力扣(LeetCode)
文章讲解:404.左叶子之和 | 代码随想录 (programmercarl.com)
视频讲解:二叉树的题目中,总有一些规则让你找不到北 | LeetCode:404.左叶子之和_哔哩哔哩_bilibili

Carl说:其实本题有点文字游戏,搞清楚什么是左叶子,剩下的就是二叉树的基本操作。

思路:通过父节点判断子节点是否为想要收集的元素,父节点左子节点不为空,且左子节点左右都为空则为我们要操作的元素。
遍历顺序:后序遍历,需要一层一层向上返回。

# 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: Optional[TreeNode]) -> int:
        # 2. 确定终止条件
        # 根节点为空,返回0
        if not root:
            return 0
        # 遍历到叶子节点时没有左右子节点,返回0
        if not root.left and not root.right:
            return 0

        # 3. 确定单层递归的逻辑,后序遍历
        # 左
        left_num = self.sumOfLeftLeaves(root.left)
        # 左子树为左叶子节点,即左子节点不为空,同时左子节点的左右子节点为空
        if root.left != None and not root.left.left and not root.left.right:
            left_num = root.left.val

        # 右
        right_num = self.sumOfLeftLeaves(root.right)

        # 中
        res = left_num + right_num

        return res

四、222.完全二叉树的节点个数

题目链接:222. 完全二叉树的节点个数 - 力扣(LeetCode)
文章讲解:222.完全二叉树的节点个数 | 代码随想录 (programmercarl.com)
视频讲解:要理解普通二叉树和完全二叉树的区别! | LeetCode:222.完全二叉树节点的数量_哔哩哔哩_bilibili

Carl说:需要了解,普通二叉树 怎么求,完全二叉树又怎么求

"""
普通二叉树解法
"""
# 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:
        res = []
 
        def dfs(node):
            if node is None:
                return
 
            dfs(node.left)        # 左
            dfs(node.right)       # 右
            res.append(node.val)  # 中
            
        dfs(root)


        return len(res)

完全二叉树思路:满二叉树节点数为2^n - 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:
    # 1. 确定递归函数的参数和返回值
    def getnum(self, node):
        # 2. 确定终止条件
        if not node:
            return 0
        # 终止条件2,判断是否为满二叉树
        # 定义两个指针分别遍历左右两侧深度
        left = node.left
        right = node.right
        leftdepth, rightdepth = 0, 0
        # 计算左侧深度
        while left:
            left = left.left
            leftdepth += 1
        # 计算右侧深度
        while right:
            right = right.right
            rightdepth += 1
        # 判断是否为满二叉树,即左右两侧深度是否相等
        if leftdepth == rightdepth:
            return 2 ** (leftdepth + 1) - 1
            # return (2 << leftdepth) - 1 也可以
        
        # 3. 确定单层递归的逻辑
        left_num = self.getnum(node.left)    # 左
        right_num = self.getnum(node.right)  # 右
        res = left_num + right_num + 1   # 中

        return res


    def countNodes(self, root: Optional[TreeNode]) -> int:
        return self.getnum(root)

Note:运算符 "<<" 表示左移位操作符,假设leftdepth = 3,那么 2 << leftdepth = 2 * 2 ^ 3 = 16

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值