question:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
resolution:
/**
* 包含两次递归:递归寻找根节点,递归比较左右子树是否相等
* @param root1
* @param root2
* @return
*/
public boolean HasSubtree(TreeNode root1,TreeNode root2) {
boolean flg = false;
//终止条件是递归到root1和root2的根节点都不为null
if(root1 != null && root2 != null){
//如果根节点相等
if(root1.val == root2.val){
//递归比较左右子树是否对应相等
flg = tree1ContainTree2(root1, root2);
}
//有一个节点不相等
if(flg == false){
//将root1的左节点作为根节点进行比较
flg = HasSubtree(root1.left,root2);
}
//如果还是不相等
if(flg == false){
//将root1的右节点作为根节点比较
flg = HasSubtree(root1.right,root2);
}
}
return flg;
}
//传入两个根节点依次递归比较是否相等
public boolean tree1ContainTree2(TreeNode root1,TreeNode root2){
//如果root1遍历完了,root2还没完就返回false
if(root1 == null && root2 != null)return false;
//如果root2遍历完了,root1无论是否遍历完都返回true
if(root2 == null) return true;
//如果有一个不想等就返回false
if(root1.val != root2.val)return false;
//如果相等就继续递归(这里需要左右子树都相等所以是相与)
return tree1ContainTree2(root1.left,root2.left) && tree1ContainTree2(root1.right,root2.right);
}
附上一段错误代码予以警示
//传入两个根节点依次递归比较是否相等
public boolean tree1ContainTree2(TreeNode root1,TreeNode root2){
boolean flg = false;
//如果相等就继续递归(这里需要左右子树都相等所以是相与)
if(root1.val == root2.val){
flg = tree1ContainTree2(root1.left,root2.left) && tree1ContainTree2(root1.right,root2.right);
//如果root1遍历完了,root2还没完就返回false
}else if(root1 == null && root2 != null){
flg = false;
//如果root2遍历完了,root1无论是否遍历完都返回true
}else if(root2 == null){
flg = true;
//如果有一个不想等就返回false
}else if(root1.val != root2.val){
flg = false;
}
return flg;
}
总结:对于树的问题主要还是要借助递归的思想,而此题需要递归寻找和子树相等的根节点,以及找到了根节点之后递归比较左右子树是否相等。以及递归的过程中的特殊情况以及终止条件这些也都需要注意,并且如何处理返回值的问题