《剑指Offer》Java刷题 NO.17 树的子结构(二叉树、递归、短路特点)
传送门:《剑指Offer刷题总目录》
时间:2020-02-26
题目:
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
先搞清楚子树和子结构的的区别:
子树的意思是只要包含了一个结点,就得包含这个结点下的所有节点.
子结构的意思是至少包含一个结点就可以
简单而言,与子树不同的是,子结构可以是A树的任意一部分。
以下示意图A子树的用红框标注的都是它的子树,蓝框标注的是其中一个子结构
思路:
利用递归以及短路特点
- 判断B是A的子结构还是A的左子树的子结构还是A的右子树的子结构,都不是的话就返回false
- 如上图所示,先判断两棵树根结点的值是否相同
- 如果不同,就继续递归往下找,比较A的左子树和右子树有无结点的值结点的值是否和B的根结点的值相等
- 直到找到相等的结点,再递归判断B树的左子树和右子树是否同时是A的子结构,判断原则:
- 先判断B树,如果B树先到了null(包含AB同时到底的情况),那么B肯定是A的子结构;
- 如果A树先到了null,那么B肯定是A的子结构;
- 如果B有某个结点的值和A的对应结点的值不相等,B也不是A的子结构
- 如果找不到相等的结点,B也不是A的子结构
Java代码:
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) {
val = x;
}
TreeNode() {
}
}
/**
* 输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
*/
public class HasSubTree {
public static boolean hasSubTree(TreeNode root1,TreeNode root2){
if(root1==null||root2==null) return false;//空树不是任意一个树的子结构
return isBigTreeSub(root1,root2)||hasSubTree(root1.left,root2)||hasSubTree(root1.right,root2);
//短路特点:如果tree2是当前大树的子结构就不用进行后面的程序了
//否则就判断tree2是不是当前大树的左子树的子结构..否则..右...
}
/**
* 子函数:判断root2是不是以当前root1为根结点的大树的子结构
* 两者根结点相等的话,就判断tree2的左子树和右子树是否同时满足是tree1的左、右子树的子结构
* 否则就不是其子结构
*/
public static boolean isBigTreeSub(TreeNode root1,TreeNode root2){
if(root2==null) return true;//初始时root1和root2都不是null,只有递归时才会出现root2==null
//而此情况(tree2先到达终点)包含root1==null和root1!=null两种情况,都应该返回true;
//反之如果先判断root1==null时,root2==null和root2!=null两种情况返回值不相同
if(root1==null) return false;//tree1先到达终点
if(root1.val==root2.val)
//找到相同的结点了!!开始看tree2的左子树和右子树是不是同时满足是tree2的左右子树的子结构
return isBigTreeSub(root1.left,root2.left)&&isBigTreeSub(root1.right,root2.right);
//短路特点:只要tree2的左子树不是tree1的左子树的子结构,就不用判断右子树了
else return false;
}
}