LeetCode题目100:递归、迭代、dfs使用栈多种算法图解相同的树

简介: LeetCode题目100:递归、迭代、dfs使用栈多种算法图解相同的树

作者介绍:10年大厂数据\经营分析经验,现任大厂数据部门负责人。

会一些的技术:数据分析、算法、SQL、大数据相关、python

欢迎加入社区:码上找工作

作者专栏每日更新:

LeetCode解锁1000题: 打怪升级之旅

python数据分析可视化:企业实战案例

python源码解读

程序员必备的数学知识与应用

备注说明:方便大家阅读,统一使用python,带必要注释,公众号 数据分析螺丝钉 一起打怪升级

题目描述

给定两个二叉树的根节点 pq,编写一个函数来检测这两棵树是否相同。如果两棵树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

示例

示例 1

输入:p = [1,2,3], q = [1,2,3]

输出:True

示例 2

输入:p = [1,2], q = [1,null,2]

输出:False


方法一:递归比较

解题步骤
  1. 基本情况:如果两个节点都是 None,返回 True。如果一个是 None 另一个不是,返回 False
  2. 值比较:如果当前两个节点的值不同,返回 False
  3. 递归比较:递归比较左子树和右子树。
Python 示例
class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
def isSameTree(p, q):
    """
    递归比较两棵树是否相同
    :param p: TreeNode, 第一棵树的根节点
    :param q: TreeNode, 第二棵树的根节点
    :return: bool, 两棵树是否相同
    """
    if not p and not q:
        return True
    if not p or not q:
        return False
    if p.val != q.val:
        return False
    return isSameTree(p.left, q.left) and isSameTree(p.right, q.right)
# 示例调用
p = TreeNode(1, TreeNode(2), TreeNode(3))
q = TreeNode(1, TreeNode(2), TreeNode(3))
print(isSameTree(p, q))  # 输出: True
算法分析
  • 时间复杂度:(O(n)),其中 (n) 是树中节点的数量,因为需要访问树中的每一个节点。
  • 空间复杂度:(O(h)),其中 (h) 是树的高度,空间消耗来自递归的栈空间。
ASCII 图解过程
[开始比较根节点]
  [1 == 1] -> True
    |---[左子树比较]
    |     [2 == 2] -> True
    |       |--[左子树比较] -> [null == null] -> True
    |       |--[右子树比较] -> [null == null] -> True
    |
    |---[右子树比较]
          [3 == 3] -> True
          |--[左子树比较] -> [null == null] -> True
          |--[右子树比较] -> [null == null] -> True
[树结构完全匹配] -> True

方法二:迭代使用队列

解题步骤
  1. 初始化队列:将根节点的对 (p, q) 加入队列。
  2. 迭代处理:从队列中取出节点对,比较这两个节点。如果不相同,则返回 False。如果相同,将他们的左孩子和右孩子按对加入队列。
  3. 重复:重复这个过程,直到队列为空。
Python 示例
from collections import deque
def isSameTree(p, q):
    """
    迭代使用队列比较两棵树是否相同
    :param p: TreeNode, 第一棵树的根节点
    :param q: TreeNode, 第二棵树的根节点
    :return: bool, 两棵树是否相同
    """
    queue = deque([(p, q)])
    while queue:
        p, q = queue.popleft()
        if not p and not q:
            continue
        if not p or not q:
            return False
        if p.val != q.val:
            return False
        queue.append((p.left, q.left))
        queue.append((p.right, q.right))
    return True
# 示例调用
p = TreeNode(1, TreeNode(2), TreeNode(3))
q = TreeNode(1, TreeNode(2), TreeNode(3))
print(isSameTree(p, q))  # 输出: True
算法分析
  • 时间复杂度:(O(n))
  • 空间复杂度:(O(n)),在最坏的情况下,如果树完全不平衡,队列可能需要存储所有节点。
ASCII 图解过程
[初始化队列] -> [(1, 1)]
  |--[比较节点 1 和 1] -> True
  |   |--[加入子节点对] -> [(2, 2), (3, 3)]
  |
  |--[比较节点 2 和 2] -> True
  |   |--[子节点都是 null,跳过]
  |
  |--[比较节点 3 和 3] -> True
      |--[子节点都是 null,跳过]
[队列空,结束] -> True

方法三:DFS 使用栈

解题步骤
  1. 使用栈模拟递归:将节点对压入栈中。
  2. 迭代比较:从栈中弹出节点对,进行比较。如果不相同,则返回 False。如果相同,将他们的左孩子和右孩子按对压入栈。
  3. 重复:直到栈为空。
Python 示例
def isSameTree(p, q):
    """
    使用栈实现深度优先搜索比较两棵树是否相同
    :param p: TreeNode, 第一棵树的根节点
    :param q: TreeNode, 第二棵树的根节点
    :return: bool, 两棵树是否相同
    """
    stack = [(p, q)]
    while stack:
        p, q = stack.pop()
        if not p and not q:
            continue
        if not p or not q or p.val != q.val:
            return False
        stack.append((p.right, q.right))
        stack.append((p.left, q.left))
    return True
# 示例调用
p = TreeNode(1, TreeNode(2), TreeNode(3))
q = TreeNode(1, TreeNode(2), TreeNode(3))
print(isSameTree(p, q))  # 输出: True
算法分析
  • 时间复杂度:(O(n))
  • 空间复杂度:(O(h)),其中 (h) 是树的高度,因为栈的最大深度由树的高度决定。
ASCII 图解过程
[初始化栈] -> [(1, 1)]
  |--[弹出节点 1 和 1] -> True
  |   |--[压入子节点对] -> [(3, 3), (2, 2)]
  |
  |--[弹出节点 2 和 2] -> True
  |   |--[子节点都是 null,跳过]
  |
  |--[弹出节点 3 和 3] -> True
      |--[子节点都是 null,跳过]
[栈空,结束] -> True

总结

这些方法提供了不同的方式来解决确定两棵树是否相同的问题。递归方法直观且易于实现,而迭代方法则在某些情况下可以提供更好的空间效率。选择哪种方法取决于具体情况和个人偏好。这些方法不仅可以应用于算法和数据结构的学习,还可以在实际开发中用于测试框架中验证复杂算法的输出结果或进行自动化测试。


欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
8月前
|
存储 算法
算法入门:专题二---滑动窗口(长度最小的子数组)类型题目攻克!
给定一个正整数数组和目标值target,找出总和大于等于target的最短连续子数组长度。利用滑动窗口(双指针)优化,维护窗口内元素和,通过单调性避免重复枚举,时间复杂度O(n)。当窗口和满足条件时收缩左边界,更新最小长度,最终返回结果。
|
8月前
|
存储 机器学习/深度学习 监控
网络管理监控软件的 C# 区间树性能阈值查询算法
针对网络管理监控软件的高效区间查询需求,本文提出基于区间树的优化方案。传统线性遍历效率低,10万条数据查询超800ms,难以满足实时性要求。区间树以平衡二叉搜索树结构,结合节点最大值剪枝策略,将查询复杂度从O(N)降至O(logN+K),显著提升性能。通过C#实现,支持按指标类型分组建树、增量插入与多维度联合查询,在10万记录下查询耗时仅约2.8ms,内存占用降低35%。测试表明,该方案有效解决高负载场景下的响应延迟问题,助力管理员快速定位异常设备,提升运维效率与系统稳定性。
351 4
|
8月前
|
存储 算法 编译器
算法入门:剑指offer改编题目:查找总价格为目标值的两个商品
给定递增数组和目标值target,找出两数之和等于target的两个数字。利用双指针法,left从头、right从尾向中间逼近,根据和与target的大小关系调整指针,时间复杂度O(n),空间复杂度O(1)。找不到时返回{-1,-1}。
|
存储 机器学习/深度学习 算法
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty 敏感词
KMP、Trie树 、AC自动机‌ ,三大算法实现 优雅 过滤 netty  敏感词
|
11月前
|
监控 算法 安全
基于 C# 基数树算法的网络屏幕监控敏感词检测技术研究
随着数字化办公和网络交互迅猛发展,网络屏幕监控成为信息安全的关键。基数树(Trie Tree)凭借高效的字符串处理能力,在敏感词检测中表现出色。结合C#语言,可构建高时效、高准确率的敏感词识别模块,提升网络安全防护能力。
281 2
|
监控 算法 数据处理
基于 C++ 的 KD 树算法在监控局域网屏幕中的理论剖析与工程实践研究
本文探讨了KD树在局域网屏幕监控中的应用,通过C++实现其构建与查询功能,显著提升多维数据处理效率。KD树作为一种二叉空间划分结构,适用于屏幕图像特征匹配、异常画面检测及数据压缩传输优化等场景。相比传统方法,基于KD树的方案检索效率提升2-3个数量级,但高维数据退化和动态更新等问题仍需进一步研究。未来可通过融合其他数据结构、引入深度学习及开发增量式更新算法等方式优化性能。
309 17
|
存储 监控 算法
局域网上网记录监控的 C# 基数树算法高效检索方案研究
在企业网络管理与信息安全领域,局域网上网记录监控是维护网络安全、规范网络行为的关键举措。随着企业网络数据量呈指数级增长,如何高效存储和检索上网记录数据成为亟待解决的核心问题。基数树(Trie 树)作为一种独特的数据结构,凭借其在字符串处理方面的卓越性能,为局域网上网记录监控提供了创新的解决方案。本文将深入剖析基数树算法的原理,并通过 C# 语言实现的代码示例,阐述其在局域网上网记录监控场景中的具体应用。
274 7
|
人工智能 算法 语音技术
Video-T1:视频生成实时手术刀!清华腾讯「帧树算法」终结闪烁抖动
清华大学与腾讯联合推出的Video-T1技术,通过测试时扩展(TTS)和Tree-of-Frames方法,显著提升视频生成的连贯性与文本匹配度,为影视制作、游戏开发等领域带来突破性解决方案。
508 4
Video-T1:视频生成实时手术刀!清华腾讯「帧树算法」终结闪烁抖动
|
算法 Java
算法系列之数据结构-Huffman树
Huffman树(哈夫曼树)又称最优二叉树,是一种带权路径长度最短的二叉树,常用于信息传输、数据压缩等方面。它的构造基于字符出现的频率,通过将频率较低的字符组合在一起,最终形成一棵树。在Huffman树中,每个叶节点代表一个字符,而每个字符的编码则是从根节点到叶节点的路径所对应的二进制序列。
454 3
 算法系列之数据结构-Huffman树
|
存储 算法 Java
算法系列之递归反转单链表
递归反转链表的基本思路是将当前节点的next指针指向前一个节点,然后递归地对下一个节点进行同样的操作。递归的核心思想是将问题分解为更小的子问题,直到达到基本情况(通常是链表末尾)。
536 5
算法系列之递归反转单链表