leetcode
leetcode 51 ~ 100
相同的树

相同的树

难度:

标签:

题目描述

给你两棵二叉树的根节点 pq ,编写一个函数来检验这两棵树是否相同。

如果两个树在结构上相同,并且节点具有相同的值,则认为它们是相同的。

 

示例 1:

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

示例 2:

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

示例 3:

输入:p = [1,2,1], q = [1,1,2]
输出:false

 

提示:

  • 两棵树上的节点数目都在范围 [0, 100]
  • -104 <= Node.val <= 104

代码结果

运行时间: 32 ms, 内存: 15 MB


/*
 * 题目思路:
 * 1. 使用Stream来处理和比较树节点的值和结构。
 * 2. 如果两棵树都是空树,则它们相同。
 * 3. 如果只有一棵树是空树,另一棵树不是,则它们不同。
 * 4. 如果两棵树的根节点值不同,则它们不同。
 * 5. 递归比较左右子树,所有条件都满足则它们相同。
 */
 
import java.util.stream.Stream;
 
public class Solution {
    public boolean isSameTree(TreeNode p, TreeNode q) {
        // 如果两棵树都是空树
        if (p == null && q == null) {
            return true;
        }
        // 如果其中一棵树为空
        if (p == null || q == null) {
            return false;
        }
        // 如果根节点值不同
        if (p.val != q.val) {
            return false;
        }
        // 递归比较左右子树
        return Stream.of(p.left, q.left).allMatch(node -> isSameTree(p.left, q.left))
                && Stream.of(p.right, q.right).allMatch(node -> isSameTree(p.right, q.right));
    }
}
 

解释

方法:

这个题解采用递归的方式来判断两棵二叉树是否相同。首先判断当前两个节点 p 和 q 是否同时为 None,如果是则说明遍历到了叶子节点且两棵树一直相同,返回 True。如果当前两个节点都不为 None 且节点值相同,则递归判断它们的左右子树是否相同。只要有一个节点为 None 或者节点值不同,则说明两棵树不同,返回 False。

时间复杂度:

O(min(m,n))

空间复杂度:

O(min(h1,h2))

代码细节讲解

🦆
在递归判断两棵树是否相同时,为何需要首先检查两个节点是否都为 None?是否可以只检查一个节点?
在递归判断两棵树是否相同时,首先检查两个节点是否都为 None 是为了确认双方都已经遍历到叶子节点的终点,这是终止递归的一个重要条件。如果只检查一个节点是否为 None,无法确保另一个节点同样为 None,这可能导致错误的判断。例如,如果一个树的节点为 None(已经没有子节点),而另一棵树的相应位置还有子节点,显然这两棵树不同。因此,必须检查两个节点是否都为 None,以确保两棵树在结构上的一致性。
🦆
递归判断两棵树是否相同时,为什么要同时检查节点值和节点的左右子树?不能只比较节点值吗?
递归判断两棵树是否相同时,仅比较节点值是不够的,因为这只能保证当前节点在值上相同,但并不能保证整棵树的结构和所有子节点的值也相同。因此,除了比较当前节点的值,还需要递归地检查左右子树是否也相同,以确保整体结构和所有细节上的一致性。如果只比较节点值,可能会忽略子树结构的不同,导致错误地判断两棵树是相同的。
🦆
在实际的编程实践中,如果遇到具有大量节点的大树,递归方法可能会导致栈溢出。有什么策略可以避免这个问题?
对于具有大量节点的大树,递归方法确实有可能导致调用栈溢出,特别是在树的深度非常大时。为了避免这种情况,可以采用迭代方法来替代递归。例如,可以使用两个栈或队列来同时迭代遍历两棵树的节点。在每一步中,从栈或队列中取出两个节点进行比较,并将它们的子节点按相同的顺序压入栈或队列中。这种迭代方法不会受到调用栈深度的限制,因此可以有效防止栈溢出问题。

相关问题