python coding with ChatGPT 打卡第16天| 二叉树:完全二叉树、平衡二叉树、二叉树的所有路径、左叶子之和

相关推荐
python coding with ChatGPT 打卡第12天| 二叉树:理论基础
python coding with ChatGPT 打卡第13天| 二叉树的深度优先遍历
python coding with ChatGPT 打卡第14天| 二叉树的广度优先遍历
python coding with ChatGPT 打卡第15天| 二叉树:翻转二叉树、对称二叉树

文章目录

完全二叉树的节点个数

Key Points

  1. 利用完全二叉树的性质:完全二叉树是一种特殊的二叉树,除了最底层,其它每一层都被完全填满,而且最底层从左到右填入节点。

相关题目

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

视频讲解

理解普通二叉树和完全二叉树的区别

重点分析

首先,我们来思考一下如何递归地解决这个问题,再考虑是否有更高效的方法。

方法一:

python 复制代码
def countNodes(root):
    if not root:
        return 0
    count_left = countNodes(root.left)
    count_right = countNodes(root.right)
    return count_left + count_right + 1

方法二:(迭代法遍历节点)

python 复制代码
def countNodes(root):
    if not root:
        return 0
    stack_record = [root]
    count = 0
    while stack_record:
        node = stack_record.pop()
        count += 1
        if node.right:
            stack_record.append(node.right)
        if node.left:
            stack_record.append(node.left)

    return count

解决这个问题的关键是利用完全二叉树的性质。

完全二叉树的高度可以通过连续地访问左子树来确定。

方法三:

如果左子树的高度等于右子树的高度,则为满二叉树

python 复制代码
def get_height(node):
    if not node:
        return 0
    height = 0
    while node:
        node = node.left
        height += 1
    return height

def get_count(height):
    num = 2**height - 1
    return num

def countNodes(root):
    if not root:
        return 0
    left_height = get_height(root.left)
    right_height = get_height(root.right)
    if left_height > right_height:
        right_count = get_count(right_height)
        left_count = countNodes(root.left)
    else:
        left_count = get_count(left_height)
        right_count = countNodes(root.right)
    return 1+left_count+right_count

方法四:

在完全二叉树中,如果递归向左遍历的深度等于递归向右遍历的深度,那说明就是满二叉树。

python 复制代码
def countNodes(root):
    if not root:
        return 0
    left = root.left
    right = root.right
    left_height = 1
    right_height = 1
    while left:
        left_height += 1
        left = left.left
    while right:
        right_height += 1
        right = right.right
    if left_height == right_height:
        return get_count(left_height)
    return countNodes(root.left) + countNodes(root.right) + 1
python 复制代码
class Solution: # 利用完全二叉树特性
    def countNodes(self, root: TreeNode) -> int:
        if not root: return 0
        count = 1
        left = root.left; right = root.right
        while left and right:
            count += 1
            left = left.left; right = right.right
        if not left and not right: # 如果同时到底说明是满二叉树,反之则不是
            return 2**count-1
        return 1 + self.countNodes(root.left) + self.countNodes(root.right)

平衡二叉树

Key Points

判断一个二叉树是否是高度平衡的,其定义是:一个二叉树每个节点的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是高度平衡的二叉树。

相关题目

110. 平衡二叉树

视频讲解

后序遍历求高度

重点分析

python 复制代码
def isBalanced(root):
    if not root:
        return True

    height = get_height(root)
    if height == -1:
        return False
    return True

def get_height(node):
    if not node:
        return 0
    left_height = get_height(node.left)
    right_height = get_height(node.right)

    if left_height == -1 or right_height == -1:
        return -1

    if abs(left_height - right_height) > 1:
        return -1
    return 1 + max(left_height, right_height)

这种方法的好处是它在计算高度的同时检查平衡性,只需遍历树一次,提高了效率。

拓展

二叉树的所有路径

相关题目

257. 二叉树的所有路径

视频讲解

递归中带着回溯

重点分析

方法一:

递归法

python 复制代码
class Solution:
    def binaryTreePaths(self, root: TreeNode) -> [str]:
        if not root:
            return []
        paths = []
        self._findPaths(root, "", paths)
        return paths
    
    def _findPaths(self, node, path, paths):
        # 更新当前路径
        currentPath = path + str(node.val)
        # 如果是叶子节点,添加路径到结果列表
        if not node.left and not node.right:
            paths.append(currentPath)
        else:
            # 如果不是叶子节点,递归遍历子节点
            if node.left:
                self._findPaths(node.left, currentPath + "->", paths)
            if node.right:
                self._findPaths(node.right, currentPath + "->", paths)

# 示例使用
# 假设我们有一个二叉树,我们可以创建这个树的节点,并调用上述函数
# 比如:
#     1
#    / \
#   2   3
#    \
#     5
# root = TreeNode(1)
# root.left = TreeNode(2)
# root.right = TreeNode(3)
# root.left.right = TreeNode(5)
# solution = Solution()
# print(solution.binaryTreePaths(root))

方法二:

迭代法(更好理解)

python 复制代码
class Solution:
    def binaryTreePaths(self, root: TreeNode) -> [str]:
        if not root:
            return []
        paths = []
        stack = [(root, str(root.val))]  # 初始化栈,包含节点和路径
        
        while stack:
            node, path = stack.pop()  # 取出当前节点和路径
            
            # 如果是叶子节点,添加路径到结果列表
            if not node.left and not node.right:
                paths.append(path)
            else:
                # 如果不是叶子节点,更新路径并将子节点加入栈
                if node.right:
                    stack.append((node.right, path + "->" + str(node.right.val)))
                if node.left:
                    stack.append((node.left, path + "->" + str(node.left.val)))
        
        return paths

在这个迭代版本中,我们使用了一个栈来存储每个节点以及从根节点到该节点的路径。这种方法模拟了递归过程的深度优先搜索(DFS)前序遍历,确保了我们能够访问到每一个叶子节点,并在到达叶子节点时记录完整的路径。

这种迭代方法提供了一种不使用系统调用栈的递归的替代方案,对于深度非常大的树来说,可以避免递归导致的栈溢出问题。

左叶子之和

Key Points

  1. 要注意是判断左叶子,不是二叉树左侧节点
  2. 判断是否是左叶子,需要通过父节点来判断

相关题目

404. 左叶子之和

视频讲解

总有一些规则让你找不到北

重点分析

方法一:

递归法:

python 复制代码
def sumOfLeftLeaves(root):
    if not root:
        return 0

    res = 0
    if isLeave(root.left):
        res += root.left.val
        res += sumOfLeftLeaves(root.right)
    else:
        res += sumOfLeftLeaves(root.left) + sumOfLeftLeaves(root.right)
    return res

def isLeave(node):
    if node:
        if not node.left and not node.right:
            return True
    return False

方法二:

迭代法(更好理解)

python 复制代码
def sumOfLeftLeaves(root):
    if not root:
        return 0
    stack_record = [root]
    res = 0
    while stack_record:
        node = stack_record.pop()
        if isLeave(node.left):
            res += node.left.val
            if node.right:
                stack_record.append(node.right)
        else:
            if node.right:
                stack_record.append(node.right)
            if node.left:
                stack_record.append(node.left)
    return res

精简版:

python 复制代码
def sumOfLeftLeaves(root):
    if not root:
        return 0
    stack_record = [root]
    res = 0
    while stack_record:
        node = stack_record.pop()
        if isLeave(node.left):
            res += node.left.val
        if node.right:
            stack_record.append(node.right)
        if node.left:
            stack_record.append(node.left)

    return res
相关推荐
lvbu_2024war0116 分钟前
MATLAB语言的网络编程
开发语言·后端·golang
single59428 分钟前
【c++笔试强训】(第四十五篇)
java·开发语言·数据结构·c++·算法
游客52030 分钟前
自动化办公-合并多个excel
开发语言·python·自动化·excel
Cshaosun39 分钟前
js版本之ES6特性简述【Proxy、Reflect、Iterator、Generator】(五)
开发语言·javascript·es6
豌豆花下猫1 小时前
Python 潮流周刊#83:uv 的使用技巧(摘要)
后端·python·ai
凡人的AI工具箱1 小时前
每天40分玩转Django:Django部署概述
开发语言·数据库·后端·python·django
RacheV+TNY2642781 小时前
深度解析:电商平台API接口的安全挑战与应对策略
人工智能·python·自动化·api
卖个几把萌1 小时前
【10】Selenium+Python UI自动化测试 邮件发送测试报告(某积载系统实例-04)
python·selenium·ui
SomeB1oody1 小时前
【Rust自学】7.2. 路径(Path)Pt.1:相对路径、绝对路径与pub关键字
开发语言·后端·rust
SomeB1oody1 小时前
【Rust自学】7.3. 路径(Path)Pt.2:访问父级模块、pub关键字在结构体和枚举类型上的使用
开发语言·后端·rust