LeetCode 951. 翻转等价二叉树
题目描述


题意分析
在二叉树的任意节点,可以交换它的左右子树。判断第一棵树能否通过若干次这样的操作,变成与第二棵树节点值和结构都相同的树。各节点可以独立选择是否翻转,也允许一次都不翻转。
操作不会改变某棵子树的根值,也不会把后代移到另一层,只改变左右方向。题目保证每棵树内部的节点值互不相同;本题只返回是否等价,不需要实际修改树或输出翻转步骤。
解法:递归比较两种子树配对
核心思路
[!blue]
定义
flipEquiv(a, b)表示以这两个节点为根的子树是否翻转等价。两者都为空时已经相同,返回真;只有一个为空时结构无法对应,返回假;两者都存在但根值不同时,交换孩子也无法改变根值,同样返回假。根值相同后,当前层只有两种可能的孩子对应关系。不翻转当前根时,第一棵树的左子树必须对应第二棵树的左子树,右子树也必须对应右子树;翻转当前根时,左子树对应右子树,右子树对应左子树。
同一种对应关系中的两对子树必须同时等价,所以使用逻辑与;两种对应关系只要任意一种成立,当前两棵子树就等价,所以外层使用逻辑或。递归继续允许子树内部自行翻转,而不是要求整棵树统一采用同一个方向。
这两种对应覆盖了当前节点的全部选择,因此不会漏解;一旦某种对应的两侧都成立,把各子树的翻转方案与当前选择组合起来,又确实能使整棵子树一致,所以也不会误判。
代码先尝试同向对应,成功就直接返回,否则再尝试交叉对应。利用根值比较尽早排除不可能的配对,全程只读取节点,不交换原树的孩子指针。
解题步骤
- 两个节点都为空时返回真;仅一个为空或根值不同则返回假。
- 递归检查左对左、右对右是否同时成立,若成立直接返回真。
- 否则检查左对右、右对左是否同时成立,并返回这个结果。
代码实现
class Solution {
public boolean flipEquiv(TreeNode root1, TreeNode root2) {
if (root1 == null && root2 == null) {
return true;
}
if (root1 == null || root2 == null || root1.val != root2.val) {
return false;
}
// 同向对应时,左右两对子树必须都匹配。
boolean sameOrder =
flipEquiv(root1.left, root2.left) && flipEquiv(root1.right, root2.right);
if (sameOrder) {
return true;
}
// 交换对应仍需同时匹配两对子树。
return flipEquiv(root1.left, root2.right) && flipEquiv(root1.right, root2.left);
}
}
func flipEquiv(root1 *TreeNode, root2 *TreeNode) bool {
if root1 == nil && root2 == nil {
return true
}
if root1 == nil || root2 == nil || root1.Val != root2.Val {
return false
}
// 同向对应时,左右两对子树必须都匹配。
sameOrder := flipEquiv(root1.Left, root2.Left) && flipEquiv(root1.Right, root2.Right)
if sameOrder {
return true
}
// 交换对应仍需同时匹配两对子树。
return flipEquiv(root1.Left, root2.Right) && flipEquiv(root1.Right, root2.Left)
}
复杂度分析
- 时间复杂度:$O(n_1 + n_2)$ 上界,其中
n_1、n_2为两树节点数。题目保证每棵树的值互异,某个非空节点只能与另一棵树中唯一同值节点继续深入,其余尝试在根值处立即结束。- 空间复杂度:$O(h)$,
h为两棵树高度的较大值,递归调用沿节点向下的路径展开,不创建新树。
关键点总结
[!green]
- 翻转只影响孩子方向,根值相等是非空子树能够等价的必要条件。
- 同一配对方案的左右两侧取与,不同配对方案之间取或。
- 每层独立选择方向,不能把判断简化为只比较原树或整棵镜像两种情况。
易错点总结
[!yellow]
- 只比较节点值集合,忽略了父子层级和分支结构,不能判断是否能通过交换达到一致。
- 将同一方案的左右条件也写成或,会在只匹配一侧时就误判成功。
- 只检查同向配对,遗漏本题允许的左右交换;只检查交叉配对则遗漏不需要交换的节点。
- 判空之前访问根值或孩子,在两树结构不同或为空时会访问空节点。
相似题目
| 题目 | 难度 | 关联与区别 |
|---|---|---|
| 100. 相同的树 | 简单 | 本题在同方向匹配失败时还可交叉匹配两个孩子,原题只判断不翻转时是否完全相同。 |
| 226. 翻转二叉树 | 简单 | 原题交换所有节点的左右孩子,本题可在不同节点独立决定是否交换。 |
转载与许可
许可
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处!