返回

路飞一起刷 LeetCode 剑指 Offer 26. 树的子结构

前端

大家好,我是挨打的阿木木,一位热衷于算法的前端摸鱼老。我打算定期与大家分享我在刷算法题时的一些思考和心得。如果你也是一位渴望提升自我逼格的摸鱼老,欢迎关注我,一起踏上学习的征程。

今天,我们就来共同探究《剑指 Offer》中的第 26 题:“树的子结构”。

题目

给定两棵二叉树 AB,判断 B 是否是 A 的子结构。

也就是说,如果我们把 B 作为一个节点插入到 A 中,B 的所有节点都能成为 A 的子节点,那么我们就可以说 BA 的子结构。

举例说明

  • 输入:

    • A = [1, 2, 3, 4, 5]
    • B = [2, 4]
  • 输出:true

  • 解释:BA 的子结构,因为我们可以将 B 插入到 A 中得到新的二叉树 [1, 2, 3, 4, 5, 2, 4],其中 B 的所有节点都成为了 A 的子节点。

  • 输入:

    • A = [1, null, 2, 3, 4, 5]
    • B = [2, 4]
  • 输出:false

  • 解释:B 不是 A 的子结构,因为如果我们将 B 插入到 A 中,B 的节点 2 的右子节点 4 无法成为 A 的子节点。

解题思路

为了判断 B 是否是 A 的子结构,我们可以采用递归的方法:

  1. 首先,我们需要比较 AB 的根节点。如果它们相等,则进一步检查 B 的左子树和右子树是否分别等于 A 的左子树和右子树。

  2. 如果 AB 的根节点不相等,则我们继续检查 A 的左子树和右子树是否包含 B 的子结构。

  3. 如果在任何情况下,我们发现 B 的所有节点都能够成为 A 的子节点,则说明 BA 的子结构。否则,B 不是 A 的子结构。

代码实现

def is_subtree(A, B):
  if not A:
    return False
  if not B:
    return True
  
  if A.val == B.val:
    return is_subtree(A.left, B.left) and is_subtree(A.right, B.right)
  else:
    return is_subtree(A.left, B) or is_subtree(A.right, B)

复杂度分析

  • 时间复杂度:O(mn),其中 m 和 n 分别为 AB 的节点数。在最坏情况下,我们需要比较每个节点,因此时间复杂度为 O(mn)。
  • 空间复杂度:O(n),其中 n 为 A 的节点数。递归调用最多会占用 O(n) 的空间。

总结

在本文中,我们探讨了如何判断一棵二叉树是否是另一棵二叉树的子结构。我们采用了一种递归的方法,比较两棵树的根节点,并检查它们是否具有相同的子结构。通过理解这个算法,我们提高了算法题解题能力,为今后解决更复杂的问题奠定了基础。

欢迎大家关注我的文章,我会持续为大家分享更多算法题解题技巧和心得。让我们一起踏上学习和成长的征程,共同提升我们的技术水平。