二叉树判断子树

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

这个题有两个种方法,一个是非递归方法,一个是递归方法。
但两种方法思路都是一样的,即对第一棵树进行遍历,在遍历的同时判断节点是否与第二颗树的根节点相等,若相等,比较同时遍历两颗树的节点,继续比较节点是否相等。若不相等,继续向下遍历。

1、非递归算法

  • 这种方法思路也不难,但是使用队列来进行遍历无法解决对称的问题。
    比如l,1.left=2和1,1.right=2。所以,笔者添加一个特殊的节点来当做空节点。避免了对称的问题,但是增加了逻辑的复杂度。
public static boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root1 == null || root2 == null) return false;
        LinkedList<TreeNode> queue = new LinkedList<>();
        TreeNode NullNode = new TreeNode(Integer.MAX_VALUE);
        queue.add(root1);
        //遍历第一棵树
        while (!queue.isEmpty()) {
            TreeNode treeNode = queue.pop();
            if (treeNode != NullNode) {
                if (treeNode.left != null) queue.offer(treeNode.left);
                else queue.offer(NullNode);
                if (treeNode.right != null) queue.offer(treeNode.right);
                else queue.offer(NullNode);
            }
            //若节点与第二颗树的根节点相等。
            if (treeNode.val == root2.val) {
                LinkedList<TreeNode> queue1 = new LinkedList<>();
                LinkedList<TreeNode> queue2 = new LinkedList<>();
                queue1.add(treeNode);
                queue2.add(root2);
                //进入循环,同时遍历两颗树,比较两颗节点
                while (true) {
                    TreeNode r1 = queue1.pop();
                    TreeNode r2 = queue2.pop();
                    if (r1.val != r2.val) break;
                    //r1
                    if (r1 != NullNode && (r1.left != null || r1.right != null)) {
                        if (r1.left != null) queue1.offer(r1.left);
                        else queue1.offer(NullNode);
                        if (r1.right != null) queue1.offer(r1.right);
                        else queue1.offer(NullNode);
                    }
                    //r2
                    if (r2 != NullNode && (r2.left != null || r2.right != null)) {
                        if (r2.left != null) queue2.offer(r2.left);
                        else queue2.offer(NullNode);
                        if (r2.right != null) queue2.offer(r2.right);
                        else queue2.offer(NullNode);
                    }
                    if ((r2.right == NullNode) || queue1.isEmpty() || queue2.isEmpty()) return true;
                }
            }
        }
        return false;
    }

2、递归算法

  • 好吧,比起非递归算法,递归算法看起来简洁得多。但递归算法得注意好判断条件,错了也不太好调试
public static boolean HasSubtree(TreeNode root1, TreeNode root2) {
        if (root1 == null || root2 == null) return false;
        return judge(root1, root2);
    }
    //遍历第一个子树同时检查第二棵树的根节点是否与节点相等,相等则调用isSame
    public static boolean judge(TreeNode root1, TreeNode root2) {
        if (root1 == null) return false;
        if (root1.val == root2.val && isSame(root1, root2)) return true;
        return judge(root1.left, root2) || judge(root1.right, root2);
    }
    //从某个节点开始,判断第二棵树是否为第一棵的子树
    public static boolean isSame(TreeNode root1, TreeNode root2) {
        if (root2 == null) return true;
        if (root1 == null) return false;
        if (root1.val != root2.val) return false;
        return isSame(root1.left, root2.left) && isSame(root1.right, root2.right);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值