二叉树题目:翻转等价二叉树

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 解法
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

标题:翻转等价二叉树

出处:951. 翻转等价二叉树

难度

4 级

题目描述

要求

对于二叉树,我们可以定义如下翻转操作:选择任意结点,然后交换其左子树和右子树。

对于两个二叉树 X 和 Y,当且仅当经过一定次数的翻转操作之后能使 X 等于 Y 时,二叉树 X 翻转等价于二叉树 Y。

给定两个二叉树的根结点 root1 \texttt{root1} root1 root2 \texttt{root2} root2,如果两个二叉树翻转等价,则返回 true \texttt{true} true,否则返回 false \texttt{false} false

示例

示例 1:

二叉树题目:翻转等价二叉树_第1张图片

输入: root1   =   [1,2,3,4,5,6,null,null,null,7,8],   root2   =   [1,3,2,null,6,4,5,null,null,null,null,8,7] \texttt{root1 = [1,2,3,4,5,6,null,null,null,7,8], root2 = [1,3,2,null,6,4,5,null,null,null,null,8,7]} root1 = [1,2,3,4,5,6,null,null,null,7,8], root2 = [1,3,2,null,6,4,5,null,null,null,null,8,7]
输出: true \texttt{true} true
解释:我们翻转值为 1 \texttt{1} 1 3 \texttt{3} 3 以及 5 \texttt{5} 5 的三个结点。

示例 2:

输入: root1   =   [],   root2   =   [] \texttt{root1 = [], root2 = []} root1 = [], root2 = []
输出: true \texttt{true} true

示例 3:

输入: root1   =   [],   root2   =   [1] \texttt{root1 = [], root2 = [1]} root1 = [], root2 = [1]
输出: false \texttt{false} false

数据范围

  • 树中结点数目在范围 [0,   100] \texttt{[0, 100]} [0, 100]
  • 树中每个结点的值都是范围 [0,   99] \texttt{[0, 99]} [0, 99] 内的唯一值

解法

思路和算法

由于每次翻转操作只会将选定结点的左子树和右子树交换,不会改变选定结点的值,因此如果两个二叉树翻转等价,则这两个二叉树的根结点一定满足以下两种情况之一。

  1. 两个二叉树的根结点都为空,即两个二叉树都为空。

  2. 两个二叉树的根结点都不为空且两个二叉树的根结点值相同。

对于第 1 种情况,由于两个二叉树都为空,因此两个二叉树翻转等价。对于第 2 种情况,需要继续对两个二叉树的左子树和右子树判断是否满足翻转等价。

由于根结点可能不翻转或翻转,因此当两个二叉树翻转等价时,可能有以下两种情况。

  1. 根结点不翻转,则第一个二叉树的左子树和第二个二叉树的左子树翻转等价,且第一个二叉树的右子树和第二个二叉树的右子树翻转等价。

  2. 根结点翻转,则第一个二叉树的左子树和第二个二叉树的右子树翻转等价,且第一个二叉树的右子树和第二个二叉树的左子树翻转等价。

由于两个二叉树是否翻转等价取决于两个二叉树的左子树和右子树之间是否存在翻转等价的关系,因此可以使用深度优先搜索实现,整个过程是一个递归的过程。

如果两个二叉树的根结点都为空,则两个二叉树翻转等价。如果两个二叉树的根结点只有一个为空,则两个二叉树不翻转等价。这两种情况是递归的终止条件。

对于其余情况,首先判断两个二叉树的根结点值是否相同,然后执行递归。

  1. 如果两个二叉树的根结点值不同,则两个二叉树不翻转等价。

  2. 如果两个二叉树的根结点值相同,则对两个二叉树的左子树和右子树调用递归。

代码

class Solution {
    public boolean flipEquiv(TreeNode root1, TreeNode root2) {
        if (root1 == null && root2 == null) {
            return true;
        }
        if (root1 == null || root2 == null) {
            return false;
        }
        return root1.val == root2.val && ((flipEquiv(root1.left, root2.left) && flipEquiv(root1.right, root2.right))
                || (flipEquiv(root1.left, root2.right) && flipEquiv(root1.right, root2.left)));
    }
}

复杂度分析

  • 时间复杂度: O ( min ⁡ ( m , n ) ) O(\min(m, n)) O(min(m,n)),其中 m m m n n n 分别是两个二叉树的结点数。虽然有两个递归调用分支(分别对应根结点不翻转和翻转),但是由于每个二叉树中的结点值各不相同,因此实际只会执行一个递归调用分支,每个结点被访问一次。

  • 空间复杂度: O ( min ⁡ ( m , n ) ) O(\min(m, n)) O(min(m,n)),其中 m m m n n n 分别是两个二叉树的结点数。空间复杂度主要是递归调用的栈空间,取决于二叉树的高度,最坏情况下二叉树的高度等于结点数。

你可能感兴趣的:(数据结构和算法,#,树,树,二叉树)