首页 > 试题广场 >

树的子结构

[编程题]树的子结构
  • 热度指数:944080 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 64M,其他语言128M
  • 算法知识视频讲解
输入两棵二叉树A,B,判断B是不是A的子结构。(我们约定空树不是任意一个树的子结构)
假如给定A为{8,8,7,9,2,#,#,#,#,4,7},B为{8,9,2},2个树的结构如下,可以看出B是A的子结构

数据范围:
0 <= A的节点个数 <= 10000
0 <= B的节点个数 <= 10000
示例1

输入

{8,8,7,9,2,#,#,#,#,4,7},{8,9,2}

输出

true
示例2

输入

{1,2,3,4,5},{2,4}

输出

true
示例3

输入

{1,2,3},{3,1}

输出

false

说明:本题目包含复杂数据结构TreeNode,点此查看相关信息
把官方的答案重新理了一下,之前总感觉官方的答案思路很难理解,想了好久才想通😑
个人的思路都写在下面注释里了,不一定好但可以参考一下
public class Solution {
    private boolean JudgeLocContain(TreeNode root1, TreeNode root2) {
        //JudgeLocContain方法为‘当前位置包含判断’
        //用于比较 ‘A树root1位置的子树’ 是否包含 B树
        //且只将B树与‘包括root1节点的 靠上部分的树’进行比较,判断是否包含
        if (root1 == null && root2 == null) {
            return true;
            //root1和root2同时遍历,刚好一起比较完毕,说明root1和root2相同,返回true
        }
        if (root1 != null && root2 == null) {
            return true;
            /*此处root2为空代表B树已递归完毕,A树还未完毕,B树与A树之前的结构相同
            题中“约定空树不是任意一个树的子结构” 针对 B树这个整体
            但该方法是对 A树当前位置子树 和 B树 “逐个节点”校验,而判断是否包含
            所以只需要在主方法开始阶段判断B树是否为空即可,此处不必考虑空树约定*/
        }
        if (root1 == null && root2 != null) {
            return false;
        } //root1已完毕,root2还未完毕,说明两者不同

        //此处隐含的剩下一种情况就是两者都还未完毕(两者都不为空,即可以比较两者值)
        if (root1.val != root2.val) {
            return false;
        }//排除两者值不相等的情况,取相等情况返回递归,保证了之前访问的节点相同
        return JudgeLocContain(root1.left, root2.left) &&
               JudgeLocContain(root1.right, root2.right);
    }

    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root2 == null) { //按照约定,判断B树整体是否为空
            return false;
        }
        if (root1 == null) {//root1为空,肯定不包含root2
            return false;
        }
        /*隐含的情况是root1和root2都不为空
        进行当前位置包含判断JudgeLocContain,并递归左右子树*/
        return JudgeLocContain(root1, root2) || HasSubtree(root1.left, root2) ||
               HasSubtree(root1.right, root2);
    }
}







发表于 2023-10-08 22:56:18 回复(0)
public class Solution {
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root2 == null || root1 == null) return false;
        if (root2.val == root1.val)
            if (HasDirectSubtree(root1.left, root2.left) &&
                    HasDirectSubtree(root1.right, root2.right)) return true;
        return HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
    }
/**
    判断 root2 是否为 root1 的直接子树
 */
    private boolean HasDirectSubtree(TreeNode root1, TreeNode root2) {
        if (root1 == null && root2 == null) return true;
        else if (root1 == null) return false;
        else if (root2 == null) return true;
        if (root1.val != root2.val) return false;
        return HasDirectSubtree(root1.left, root2.left) &&
               HasDirectSubtree(root1.right, root2.right);
    }
}
直接子树指的是从根节点开始比较的结果
发表于 2023-05-05 11:53:06 回复(0)
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
       public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        //两个树有一个为null 都返回false
        if(root1==null||root2==null)
            return false;
        boolean result=false;
        //找到相同的结点后 判断root2的左右子树是否是root1的左右子树的一部分
        if(root1.val==root2.val) {
            result = isSame(root1, root2);
        }
        //root2可能在root1的左子树上
        if(!result){
            result = HasSubtree(root1.left, root2);
        }
        if(!result){
            result = HasSubtree(root1.right, root2);
        }
        return result;
    }

   

   
//判断以root1和root2为根的树 root2是不是root1的一部分
    private boolean isSame(TreeNode root1, TreeNode root2) {
        //第二个树遍历完成(root2是root1的一部分)
        if (root2 == null)
            return true;
        if (root1 == null)
            return false;
        if (root1.val == root2.val) {
            return isSame(root1.left, root2.left) && isSame(root1.right, root2.right);
        }
        return false;
    }

}

发表于 2023-04-02 09:24:22 回复(0)
//可以用双重递归的思想,对于A树的每个节点,判断它是不是和B树是相同的树,如果A有这样的节点,以它开头有和B树完全一样的树,即B是A的子树
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        //如果root1为空或者root2为空,那么就无法继续递归下去看看有没有子树符合要求了,就直接返回false
        if(root1==null || root2==null){
            return false;
        }
        //如果A树中有这么一个root,以它开头的树有一部分和B树完全一样,那么就认为A树包含B树
        if(judge(root1,root2)){
            return true;
        }
        //对以A树每个节点开头的树,如果任何一个树满足条件,都会返回true
        return HasSubtree(root1.left,root2)||HasSubtree(root1.right,root2);
    }
    public boolean judge(TreeNode root1,TreeNode root2){
        //同时遍历root1开头的树和B树,如果遍历到B树这个节点为空了,说明之前都没发生过违法行为,返回true
        //注意 B树节点为空的时候,A树这个节点是可以有值的
        if(root2==null){
            //以B树为主,B树是宝宝,整个安全的不返回false的遍历完B树就算成功
            return true;
        }
        //如果走到这了,B树这个节点不为空,那么如果此时A树这个节点为空,那么显然不符合要求
        if(root1==null){
            return false;
        }
        //如果走到这个,说明这两个节点同时不为空,那么如果它们的值不相同,它们也不是完全相同的一棵树
        if(root1.val!=root2.val){
            return false;
        }
        //这个节点的左子树的每个节点和右子树的每个节点都得符合要求,但凡有一对节点不符合要求返回false的,就整个失败
        return judge(root1.left,root2.left) && judge(root1.right, root2.right);
    }
}

发表于 2022-10-19 14:56:19 回复(1)
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;

    }

}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1TreeNode root2) {
        if (root1 == null || root2 == null) {
            return false;
        }
        boolean flag = false;
        if (root1.val == root2.val) {
            flag = help(root1, root2);
        }
        if (flag != true)
            flag = HasSubtree(root1.left, root2);
        if (flag != true)
            flag = HasSubtree(root1.right, root2);
        return flag;
    }
    public boolean help(TreeNode parTreeNode son) {
        if (par == null && son != null) {
            return false;
        }
        if (son == null) {
            return true;
        }
        if (par.val != son.val) {
            return false;
        }
        return help(par.leftson.left) && help(par.rightson.right);
    }
}

发表于 2022-09-28 17:30:30 回复(0)
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root2 == null){
            return false;
        }
        return Same(root1, root2);
    }
    
    boolean Same(TreeNode root1,TreeNode root2){
        if(root2 == null){
            return true;
        }
        if(root1 == null){
            return false;
        }
        if(root1.val == root2.val){
            if(Same(root1.left, root2.left) && Same(root1.right, root2.right))
                return true;
        }
         return Same(root1.left, root2) || Same(root1.right, root2);
    }  
}

发表于 2022-09-15 17:28:40 回复(0)
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root2 == null || root1 == null){
            return false;
        }
        if(root1.val == root2.val){
            if( (root2.left == null || HasSubtree(root1.left, root2.left)) && (root2.right == null || HasSubtree(root1.right, root2.right))){
                return true;
            }
        }
        return HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
    }
}


发表于 2022-08-10 23:52:36 回复(0)
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1==null||root2==null)
            return false;
        return dps(root1,root2);
    }
    public boolean dps(TreeNode root1,TreeNode root2){
        if(root2==null)
            return true;
        if(root1==null)
            return false;
        if(root1.val==root2.val&&dps(root1.left,root2.left)&&dps(root1.right,root2.right))
            return true;
        else
            return dps(root1.left,root2)||dps(root1.right,root2);
    }
}

发表于 2022-06-09 15:25:32 回复(0)
public class Solution {
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        //当一个节点存在另一个不存在时
        if (root1 == null || root2 == null)
            return false;
        if (root1.val == root2.val && curd(root1.left, root2.left) &&
                curd(root1.right, root2.right)) {
            return true;
        }
        return HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);

    }

    public boolean curd(TreeNode A, TreeNode B) {
        if (B == null) {
            return true;
        }
        if (A == null) {
            return false;
        }
        if (A.val == B.val) {
            return curd(A.left, B.left) && curd(A.right, B.right);
        } else {
            return false;
        }

    }

}

发表于 2022-06-03 17:49:49 回复(0)
public class Solution {
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        //第一步,先确定起始比较位置
        if (root1 == null || root2 == null) {
            return false;
        }

        boolean ans = false;
        //确立起始比较位置,从该位置尝试比较
        if (root1.val == root2.val) {
            ans = isSameFromBegin(root1, root2);
        }
        //说明root1.val != root2.val&nbs***bsp;上面的起始位置不满足需求,换一个起始位置
        if (ans != true) {//在左子树中找找
            ans = HasSubtree(root1.left, root2);
        }
        if (ans != true) {//在右子树中找找
            ans = HasSubtree(root1.right, root2);
        }
        return ans;
    }

    private boolean isSameFromBegin(TreeNode root1, TreeNode root2) {
        if (root2 == null) {//roo2为null,说明已经比较完了
            return true;
        }
        if (root1 == null){ //root1为空,说明beginSub不是你的子树
            return false;
        }
        if (root1.val != root2.val){//说明整树中,有不相等的节点
            return false;
        }
        //分别比较左右左右子树,必须都是相等的
        return isSameFromBegin(root1.left,root2.left) && isSameFromBegin(root1.right,root2.right);
    }
}

发表于 2022-05-25 10:54:19 回复(0)
/**
public class TreeNode {
    int val = 0;
    TreeNode left = null;
    TreeNode right = null;

    public TreeNode(int val) {
        this.val = val;
    }
}
*/
public class Solution {
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root1 == null || root2 == null) return false;

        return isSame(root1, root2) || HasSubtree(root1.left, root2) ||
               HasSubtree(root1.right, root2);
    }
    public boolean isSame(TreeNode root1, TreeNode root2) {
        if (root2 == null) return true;
        if (root1 == null || root1.val != root2.val) return false;

        return isSame(root1.left, root2.left) && isSame(root1.right, root2.right);

    }
}

发表于 2022-05-11 09:58:48 回复(0)
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1 == null || root2 == null) return false;
        return dfs(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);
    }
    
    // 不是完全比较两颗树完全相同,而是p覆盖了q
    private boolean dfs(TreeNode p, TreeNode q) {
        if(q == null) return true;
        if(p == null) return false;
        if(p.val != q.val) return false;
        return dfs(p.left, q.left) && dfs(p.right, q.right);
    }
}

发表于 2022-05-01 17:21:29 回复(0)
public class Solution {
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root1 == null || root2 == null)return false;
        return trySubtree(root1, root2) || HasSubtree(root1.left, root2) ||
               HasSubtree(root1.right, root2);
    }

    boolean trySubtree(TreeNode p1, TreeNode p2) {
        if (p2 == null)return true;
        if (p1 == null || p1.val != p2.val)return false;
        if (p1.val == p2.val && trySubtree(p1.left, p2.left) &&
                trySubtree(p1.right, p2.right))return true;
        return false;
    }
}


发表于 2022-03-28 23:01:38 回复(0)
public class Solution {
    public boolean isSame(TreeNode root1,TreeNode root2){
    //如果root2为空,则为true(不需要考虑root1的状况)
    if(root2 == null) return true;
    if(root1 == null) return false;
    //判断首节点的值,然后root1与root2的左子树,然后root1与root2的右子树
    return root1.val == root2.val  &&  isSame(root1.left, root2.left)  &&  isSame(root1.right, root2.right);
    }
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1 == null || root2 == null) return false;
        return isSame(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right,root2);
    }
}

发表于 2022-03-25 15:31:03 回复(0)
public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {  
        //当前节点不相等,分别找左和右
        //当前节点相等,判断是否相等
        //特殊情况:A或B其中之一为空,return false;
        if(root1==null || root2==null) return false;
        if(root1.val==root2.val){  //当前节点相等,判断左右是否相等(左可以多);
            if(isSame(root1.left,root2.left) && isSame(root1.right,root2.right)){
                return true;
            }
        }
        return HasSubtree(root1.left,root2) || HasSubtree(root1.right,root2);
    }

    public boolean isSame(TreeNode root1,TreeNode root2){
        if(root2==null) return true; //直到root2为空为止
        if(root1==null) return false; 

        if(root1.val!=root2.val) return false;
        return isSame(root1.left,root2.left) && isSame(root1.right,root2.right);

    }
}
发表于 2022-03-02 10:32:10 回复(0)
    public boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root1 == null || root2 == null) {
            return false;
        }

        return HasSubtreeHelp(root1, root2) || HasSubtree(root1.left, root2) || HasSubtree(root1.right, root2);

    }

    private boolean HasSubtreeHelp(TreeNode root1, TreeNode root2) {
        if (root1 == null || root2 == null) {
            return false;
        }

        if (root1.val == root2.val) {
            boolean left = true;
            if (root2.left != null) {
                left = HasSubtreeHelp(root1.left, root2.left);
            }

            boolean right = true;
            if (root2.right != null) {
                right = HasSubtreeHelp(root1.right, root2.right);
            }

            return right && left;
        } else {
            return false;
        }
    }

发表于 2022-02-27 20:57:22 回复(1)