力扣250题:计算同值子树数量(Count Univalue Subtrees)

在本篇文章中,我们将详细解读力扣第250题"统计同值子树"。通过学习本篇文章,读者将掌握如何在二叉树中统计所有节点值相同的子树数量,并了解相关的复杂度分析和模拟面试问答。每种方法都将配以详细的解释,以便于理解。

问题描述

力扣第250题"统计同值子树"描述如下:

复制代码
给定一棵二叉树,统计其中节点值都相同的子树的数量。

示例:

解题思路

方法一:递归后序遍历

  1. 初步分析:

• 同值子树指的是子树中的所有节点值都相同。因此,我们可以从叶子节点开始递归地检查每棵子树是否是同值子树。

• 通过后序遍历,我们可以先检查左右子树是否是同值子树,然后判断当前子树是否是同值子树。

  1. 步骤:

• 使用一个全局变量 count 记录同值子树的数量。

• 定义一个递归函数 is_unival_subtree,返回当前子树是否是同值子树:

• 如果当前节点为空,返回 True(空树是同值子树)。

• 递归检查左右子树是否是同值子树。

• 如果当前节点与左右子树的根节点值不同,则当前子树不是同值子树。

• 如果当前节点的值与左右子树的值相同,则当前子树是同值子树,计数器加一。

• 最后返回计数器的值。

代码实现

class TreeNode:

def init (self, val=0, left=None, right=None):

self.val = val

self.left = left

self.right = right

def countUnivalSubtrees(root):

count = 0

复制代码
def is_unival_subtree(node):
    nonlocal count
    if not node:
        return True
    
    left_is_unival = is_unival_subtree(node.left)
    right_is_unival = is_unival_subtree(node.right)
    
    if not left_is_unival or not right_is_unival:
        return False
    
    if node.left and node.val != node.left.val:
        return False
    if node.right and node.val != node.right.val:
        return False
    
    count += 1
    return True

is_unival_subtree(root)
return count

测试案例

root = TreeNode(5, TreeNode(1, TreeNode(5), TreeNode(5)), TreeNode(5, None, TreeNode(5)))

print(countUnivalSubtrees(root)) # 输出: 4

复杂度分析

• 时间复杂度:O(n),其中 n 是树中的节点数量。每个节点只需访问一次。

• 空间复杂度:O(h),其中 h 是树的高度。递归调用栈的深度等于树的高度。

模拟面试问答

问题 1:你能描述一下如何解决这个问题的思路吗?

回答:我们使用后序遍历的递归方法解决这个问题。从叶子节点开始检查左右子树是否是同值子树,然后判断当前子树是否是同值子树。如果当前节点值与左右子树的值相同,则当前子树是同值子树,计数器加一。

问题 2:为什么选择使用后序遍历来解决这个问题?

回答:后序遍历能够自然地从叶子节点开始递归检查子树的性质。通过先检查左右子树,我们可以在判断当前子树是否是同值子树时确保左右子树的结果已经确定。这种方式简洁且高效,适合处理树形结构的问题。

问题 3:你的算法的时间复杂度和空间复杂度是多少?

回答:时间复杂度为 O(n),因为我们需要访问每个节点一次。空间复杂度为 O(h),因为递归调用栈的深度等于树的高度,在最坏情况下为 O(n)(链式树)。

问题 4:在代码中如何处理边界情况?

回答:对于空树,代码通过检查节点是否为空返回 True,并且不会增加计数器。对于只有一个节点的树,代码会正确地识别为同值子树,计数器加一。

问题 5:你能解释一下递归函数在这个问题中的具体作用吗?

回答:递归函数 is_unival_subtree 用于判断当前子树是否是同值子树。通过递归调用左右子树的结果,我们可以逐层向上返回是否满足同值子树的条件,并在每次满足条件时增加计数器。

问题 6:在代码中如何确保返回的结果是正确的?

回答:通过逐步递归遍历每个节点,并在每次递归返回时检查是否满足同值子树的条件,确保计数器记录的结果是正确的。测试用例验证了代码在多种树结构下的正确性。

问题 7:你能举例说明在面试中如何回答优化问题吗?

回答:在面试中,如果被问到如何优化算法,我会首先分析当前算法的时间复杂度和空间复杂度。由于时间复杂度已经是 O(n),进一步优化的空间有限。可以讨论如何在极端情况下优化递归调用栈的深度,或者使用迭代的方法替代递归。

问题 8:如何验证代码的正确性?

回答:通过编写详细的测试用例,涵盖所有可能的树结构,如空树、只有一个节点的树、所有节点值相同的树等,确保每个测试用例的结果都符合预期。此外,还可以通过手工推演树的遍历过程,验证代码逻辑的正确性。

问题 9:你能解释一下解决"统计同值子树"问题的重要性吗?

回答:解决"统计同值子树"问题展示了对树形结构的递归遍历和性质判断的能力,尤其是在判断子树性质时的技巧。通过掌握这个问题的解决方法,可以提高对树形数据结构的理解,并为处理更复杂的树形问题打下基础。

问题 10:在处理大数据集时,算法的性能如何?

回答:由于算法的时间复杂度为 O(n),在处理大数据集时性能仍然良好。即使树中包含大量节点,算法也能在一次遍历中完成所有检查。空间复杂度为 O(h),对于高度较小的平衡树,内存使用也非常少。

总结

本文详细解读了力扣第250题"统计同值子树",通过使用后序遍历的递归方法高效地统计二叉树中的同值子树数量,并提供了详细的解释和模拟面试问答。希望读者通过本文的学习,能够在力扣刷题的过程中更加得心应手。

相关推荐
智慧物业老杨4 小时前
物业绿化数智化权责管控方案:基于工单平台的双层权限追溯模块落地实践
python
Metaphor6925 小时前
使用 Python 在 Word 文档中添加批注
python·word
FreakStudio5 小时前
WIZnet 开源方案分享:W55MH32 开发板 + 小智 AI实现以太网版本的小智机器人
python·单片机·嵌入式·大学生·面向对象·并行计算·电子diy·电子计算机
会周易的程序员5 小时前
使用 pybind11 封装 C++ 日志库 microLog 为 Python 模块
java·c++·python·物联网·架构·日志·aiot
米饭不加菜5 小时前
NE555 定时器应用——声光控制/延时开关电路
经验分享·硬件工程
风止何安啊5 小时前
🚦 前端并发请求 “交通管制”:别让你的接口堵成早高峰
前端·javascript·面试
一只专注api接口开发的技术猿5 小时前
电商评论自动化监控与情感数据分析完整落地教程(附可直接运行 Python 代码)
大数据·数据库·python·数据分析·自动化
Fox爱分享5 小时前
字节二面:1000瓶酒,有一瓶是毒药,多少只老鼠可以查出来?
算法·面试·程序员
HAPPY酷5 小时前
【ROS2】 Conda 环境搭建(命令行版)
linux·运维·python·ubuntu·机器人·conda
+wacyltd大模型备案算法备案6 小时前
大模型评估测试题库怎么建?风险分类、测试样本的完整方法
人工智能·算法·安全·分类·大模型·大模型备案·大模型上线登记