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
相关推荐
m0_571957581 小时前
Java | Leetcode Java题解之第543题二叉树的直径
java·leetcode·题解
一点媛艺2 小时前
Kotlin函数由易到难
开发语言·python·kotlin
姑苏风2 小时前
《Kotlin实战》-附录
android·开发语言·kotlin
奋斗的小花生3 小时前
c++ 多态性
开发语言·c++
魔道不误砍柴功3 小时前
Java 中如何巧妙应用 Function 让方法复用性更强
java·开发语言·python
pianmian13 小时前
python数据结构基础(7)
数据结构·算法
闲晨3 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
_.Switch4 小时前
高级Python自动化运维:容器安全与网络策略的深度解析
运维·网络·python·安全·自动化·devops
老猿讲编程4 小时前
一个例子来说明Ada语言的实时性支持
开发语言·ada
Chrikk5 小时前
Go-性能调优实战案例
开发语言·后端·golang