[Leetcode] 0100. 相同的树

100. 相同的树

题目描述

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

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

示例 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

解法

方法一:DFS

我们可以使用 DFS 递归的方法来解决这个问题。

首先判断两个二叉树的根节点是否相同,如果两个根节点都为空,则两个二叉树相同,如果两个根节点中有且只有一个为空,则两个二叉树一定不同。如果两个根节点都不为空,则判断它们的值是否相同,如果不相同则两个二叉树一定不同,如果相同,则分别判断两个二叉树的左子树是否相同以及右子树是否相同。当以上所有条件都满足时,两个二叉树才相同。

时间复杂度 \(O(\min(m, n))\),空间复杂度 \(O(\min(m, n))\)。其中 \(m\) 和 \(n\) 分别是两个二叉树的节点个数。空间复杂度主要取决于递归调用的层数,递归调用的层数不会超过较小的二叉树的节点个数。

方法二:BFS

我们也可以使用 BFS 迭代的方法来解决这个问题。

首先将两个二叉树的根节点分别加入两个队列。每次从两个队列各取出一个节点,进行如下比较操作。如果两个节点的值不相同,则两个二叉树的结构一定不同,如果两个节点的值相同,则判断两个节点的子节点是否为空,如果只有一个节点的左子节点为空,则两个二叉树的结构一定不同,如果只有一个节点的右子节点为空,则两个二叉树的结构一定不同,如果左右子节点的结构相同,则将两个节点的左子节点和右子节点分别加入两个队列,对于下一次迭代,将从两个队列各取出一个节点进行比较。当两个队列同时为空时,说明我们已经比较完了所有节点,两个二叉树的结构完全相同。

时间复杂度 \(O(\min(m, n))\),空间复杂度 \(O(\min(m, n))\)。其中 \(m\) 和 \(n\) 分别是两个二叉树的节点个数。空间复杂度主要取决于队列中的元素个数,队列中的元素个数不会超过较小的二叉树的节点个数。

Python3

DFS:

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if not p and not q:
            return True
        elif not p or not q:
            return False
        elif p.val != q.val:
            return False
        else:
            return self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)

BFS:

python 复制代码
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def isSameTree(self, p: TreeNode, q: TreeNode) -> bool:
        if p == q:
            return True
        if p is None or q is None:
            return False
        q1, q2 = deque([p]), deque([q])
        while q1 and q2:
            a, b = q1.popleft(), q2.popleft()
            if a.val != b.val:
                return False
            la, ra = a.left, a.right
            lb, rb = b.left, b.right
            if (la and not lb) or (lb and not la):
                return False
            if (ra and not rb) or (rb and not ra):
                return False
            if la:
                q1.append(la)
                q2.append(lb)
            if ra:
                q1.append(ra)
                q2.append(rb)
        return True

C++

cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
        if (p == nullptr && q == nullptr) {
            return true;
        } else if (p == nullptr || q == nullptr) {
            return false;
        } else if (p->val != q->val) {
            return false;
        } else {
            return isSameTree(p->left, q->left) && isSameTree(p->right, q->right);
        }
    }
};
cpp 复制代码
/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
        if (p == q) return true;
        if (!p || !q) return false;
        queue<TreeNode*> q1{{p}};
        queue<TreeNode*> q2{{q}};
        while (!q1.empty() && !q2.empty())
        {
            p = q1.front();
            q = q2.front();
            if (p->val != q->val) return false;
            q1.pop();
            q2.pop();
            TreeNode *la = p->left, *ra = p->right;
            TreeNode *lb = q->left, *rb = q->right;
            if ((la && !lb) || (lb && !la)) return false;
            if ((ra && !rb) || (rb && !ra)) return false;
            if (la)
            {
                q1.push(la);
                q2.push(lb);
            }
            if (ra)
            {
                q1.push(ra);
                q2.push(rb);
            }
        }
        return true;
    }
};
相关推荐
jktantan1 小时前
注解式脱敏:用 Jackson 的 ContextualSerializer 做字段级策略(一)
spring boot·后端·算法·spring cloud·系统架构
Dream it possible!14 小时前
LeetCode 面试经典 150_多维动态规划_交错字符串(97_C++_中等)
算法·leetcode·面试·动态规划
心抵鹊14 小时前
算法之双指针系列(一)
算法·leetcode
十二14 小时前
【洛谷题解】P1083 [NOIP 2012 提高组] 借教室(二分答案 + 差分)
数据结构·c++·算法·蓝桥杯
小此方15 小时前
[算法实战论:动态规划]回文串问题的dp解法,回文串问题的母题,以及以此为基础的派生题
算法·动态规划
Pniubi16 小时前
力扣560.和为k的子数组
算法·leetcode·职场和发展
D e re k ZH16 小时前
C++ 从零入门(一):基础语法与程序结构
数据结构·c++·算法
Pniubi17 小时前
力扣438.找到字符串中所有字母异位词
算法·leetcode·职场和发展
東隅已逝,桑榆非晚19 小时前
算法6. 双指针法-查找总价格为目标的两个商品
c++·学习·算法
Eyfcom20 小时前
〖物联网终端实战 01〗UWB 室内高精度定位:仓储 AGV 与人员的厘米级轨迹追踪
物联网·算法·物流系统·快递系统·跨境物流快递系统·物联网终端实战