《剑指Offer》Java刷题 NO.17 树的子结构

《剑指Offer》Java刷题 NO.17 树的子结构(二叉树、递归、短路特点)

传送门:《剑指Offer刷题总目录》

时间:2020-02-26
题目:
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)


先搞清楚子树和子结构的的区别:
子树的意思是只要包含了一个结点,就得包含这个结点下的所有节点.
子结构的意思是至少包含一个结点就可以
简单而言,与子树不同的是,子结构可以是A树的任意一部分。
以下示意图A子树的用红框标注的都是它的子树,蓝框标注的是其中一个子结构
在这里插入图片描述
思路:
利用递归以及短路特点

  1. 判断B是A的子结构还是A的左子树的子结构还是A的右子树的子结构,都不是的话就返回false
  2. 如上图所示,先判断两棵树根结点的值是否相同
  3. 如果不同,就继续递归往下找,比较A的左子树和右子树有无结点的值结点的值是否和B的根结点的值相等
  4. 直到找到相等的结点,再递归判断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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值