题意
给你两棵二叉树的根节点 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
分析
本题我们还是使用解决二叉树问题中最常用的办法——“递归”。
假设我们现在获得了两棵树的根节点(p和q),一眼看出他俩是相同的很难,但也有例外,比如说两个都是null,空树自然是一样的。
再换另外一个角度,想要一眼看出两棵树是不同的,只要p.val != q.val,我们就能分辨出。
至于其他的情况,就不能这么简单地分辨了,因为涉及到左子树和右子树相同的情况,但是不要忘记——递归!
只要继续递归处理各自的左子树和右子树,问题就迎刃而解了,换句话说,p的左子树必然和q的左子树是相同的,p的右子树必然和q的右子树也是相同的,而左子树和右子树同样也是二叉树。
这时候整个算法的大概框架就浮现出来了——以递归为基础,先判断我们前面提到的两种最直观的情况,否则就递归判断左子树和右子树!
好,来看整个题解,看一眼注释基本就明白了,非常简单。
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode() {}
* TreeNode(int val) { this.val = val; }
* TreeNode(int val, TreeNode left, TreeNode right) {
* this.val = val;
* this.left = left;
* this.right = right;
* }
* }
*/
class Solution {
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p==null&&q==null){
return true;
}else if(p==null||q==null){
return false;
}else if(p.val != q.val){
return false;
}else{
return p.val==q.val&&isSameTree(p.left,q.left)&&isSameTree(p.right,q.right);
}
}
}
因为最多只可能遍历整个树的所有节点一次,所以时间复杂度为,非常优秀。
好,对于输入 p = [1,2] 和 q = [1,null,2],我们来模拟一下整个题解过程:
树 p 的结构:
1
/
2
树 q 的结构:
1
\
2
按照题解的方法,我们逐步比较这两棵树是否相同:
- 初始调用 isSameTree:
- 首先比较根节点 p(值为1)和根节点 q(值为1)。它们的值相等,所以我们继续。
- 递归比较左子树:
- 接下来,我们比较 p 的左子树(值为2)和 q 的左子树(null)。
- 因为 p 的左子树是非空的,而 q 的左子树是空的,所以这里它们不相同。
- 此时,方法返回 false。
- 递归比较右子树:
- 这一步在本例中不会执行,因为一旦左子树的比较返回了 false,整个方法就会立即返回 false。
所以,根据题解的逻辑,这两棵树不是相同的树,最终结果为 false。这是因为尽管它们的根节点相同,但它们的左子树不同(一个是非空,另一个是空)。树的结构和节点值都需要完全匹配,才能认为两棵树是相同的。
总结
简单的代码,简单的思路,背后蕴藏着的其实是我们不断锤炼的解题能力