leetcode
leetcode 2651 ~ 2700
另一棵树的子树

另一棵树的子树

难度:

标签:

题目描述

Given the roots of two binary trees root and subRoot, return true if there is a subtree of root with the same structure and node values of subRoot and false otherwise.

A subtree of a binary tree tree is a tree that consists of a node in tree and all of this node's descendants. The tree tree could also be considered as a subtree of itself.

 

Example 1:

Input: root = [3,4,5,1,2], subRoot = [4,1,2]
Output: true

Example 2:

Input: root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
Output: false

 

Constraints:

  • The number of nodes in the root tree is in the range [1, 2000].
  • The number of nodes in the subRoot tree is in the range [1, 1000].
  • -104 <= root.val <= 104
  • -104 <= subRoot.val <= 104

代码结果

运行时间: 42 ms, 内存: 16.3 MB


/*
题目思路:
1. 使用 Java Stream API 实现。
2. 我们定义一个方法 isSubtree 使用递归和流来判断 subRoot 是否是 root 的子树。
3. 在 root 的每个节点上,检查 isSameTree 函数是否为 true。
4. 如果 isSameTree 为真,返回 true;否则检查左子树和右子树。
*/
import java.util.stream.Stream;

public class Solution {
    public boolean isSubtree(TreeNode root, TreeNode subRoot) {
        if (root == null) return subRoot == null;
        return isSameTree(root, subRoot) || Stream.of(root.left, root.right).anyMatch(node -> isSubtree(node, subRoot));
    }

    private boolean isSameTree(TreeNode s, TreeNode t) {
        if (s == null && t == null) return true;
        if (s == null || t == null) return false;
        if (s.val != t.val) return false;
        return isSameTree(s.left, t.left) && isSameTree(s.right, t.right);
    }
}

解释

方法:

该题解使用了哈希的思想。首先通过 searchsub 函数计算出子树 subRoot 的哈希值,然后在主树 root 中通过 searchmain 函数查找是否存在一个子树的哈希值与 subRoot 的哈希值相等。如果存在,则说明主树中包含了与 subRoot 结构相同的子树,返回 True;否则返回 False。在计算哈希值时,使用了节点的值、左子树的哈希值和右子树的哈希值,并通过质数相乘的方式组合,以尽量避免哈希冲突。

时间复杂度:

O(m + n)

空间复杂度:

O(n)

代码细节讲解

🦆
为什么选择使用哈希方法来解决这个问题?是因为它比其他方法例如递归比较更高效吗?
哈希方法被选择来解决这个问题主要是因为它在某些情况下可以提供比简单递归方法更高的效率。使用哈希方法,我们可以将每个节点的子树转化为一个哈希值,这样就可以通过比较哈希值来快速判断两个子树是否相同,而不需要再进行逐节点的比较。这种方法尤其在树的结构复杂或树的大小较大时,可以显著减少比较次数和运行时间。然而,这种方法可能需要额外的空间来存储每个节点的哈希值,并且还需要处理哈希冲突的问题。
🦆
在哈希函数中,使用了特定的质数31和179以及1000079进行计算。这些质数的选择有什么特别的理由或考虑吗?
在哈希函数中使用特定的质数,如31、179和1000079,是为了减少哈希冲突的概率并尽可能均匀地分布哈希值。质数在哈希函数中常用来这种目的,因为它们在进行模运算时不易产生规律性,从而帮助更随机地分布哈希值。选用不同的质数组合可以根据具体的应用场景调整,以达到最佳的哈希效果。1000079这样的大质数通常用于最终的模运算,以限制哈希值的范围并减少冲突。
🦆
哈希冲突是如何被处理的?在哈希值相同的情况下,是否有额外的步骤来确认两棵子树确实是结构和节点值都相同?
在题解中,哈希冲突的处理似乎没有被直接提及。理想情况下,如果哈希值相同,我们应该进一步检查两棵树的结构和节点值以确保它们确实相同,因为不同的树可能会有相同的哈希值(尽管这种情况较少)。在实际应用中,当我们发现两个哈希值相同时,可以再通过递归的方式对这两棵子树进行详细比较,确保它们在结构和节点值上完全一致。这一步骤是必要的,以避免因哈希冲突而错误地判断两棵树相同。

相关问题

统计同值子树

统计同值子树

出现次数最多的子树元素和

给你一个二叉树的根结点 root ,请返回出现次数最多的子树元素和。如果有多个元素出现的次数相同,返回所有出现次数最多的子树元素和(不限顺序)。

一个结点的 「子树元素和」 定义为以该结点为根的二叉树上所有结点的元素之和(包括结点本身)。

 

示例 1:

输入: root = [5,2,-3]
输出: [2,-3,4]

示例 2:

输入: root = [5,2,-5]
输出: [2]

 

提示:

  • 节点数在 [1, 104] 范围内
  • -105 <= Node.val <= 105