剑指Offer-题26(Java版):树的子结构

参考自:《剑指Offer——名企面试官精讲典型编程题》

题目:树的子结构
输入两棵二叉树A和B,判断B是不是A的子结构。
例如:
A:

//            10
//         /      \
//        6        14
//       /\        /\
//      4  8     12  16

B:

//        6
//       /\
//      4  8

B是A的子树

主要思路
第一步:在树A中找到和树B的根节点值一样的结点R,该过程可通过递归遍历树A的节点实现(先找父节点,再找左右子节点)。
第二步:判断在树A中以R为根节点的子树结构是否和树B的结构一样,可通过递归来判断它们各自的父节点和左右子节点是否一样。

关键点:递归,二叉树遍历

时间复杂度:O(nB)~O(nAnB)

public class SubTree {
    public static void main(String[] args) {
        TreeNode root1 = TreeNode.generateBinaryTree();
        TreeNode root2 = TreeNode.generateSubTree();
        System.out.println(hasSubtree(root1, root2));
    }

    private static boolean hasSubtree(TreeNode root1, TreeNode root2) {
        boolean result = false;
        if (root1 == null || root2 == null) {
            return false;
        }
        if (root1.val == root2.val) {
            result = isTree1HaveTree2(root1, root2);
        }
        if (!result) {
            //判断是否是root1左树的子树
            result = hasSubtree(root1.left, root2);
        }
        if (!result) {
            //判断是否是root1右树的子树
            result = hasSubtree(root1.right, root2);
        }
        return result;
    }

    private static boolean isTree1HaveTree2(TreeNode tree1, TreeNode tree2) {
        //Tree2遍历完,说明是子树,返回true
        if (tree2 == null) {
            return true;
        }
        //如果Tree2还没有遍历完,Tree1却遍历完了,返回false
        if (tree1 == null) {
            return false;
        }
        //节点值不相等,返回false
        if (tree1.val != tree2.val) {
            return false;
        }
        //判断左右子树是否满足条件
        return isTree1HaveTree2(tree1.left, tree2.left) && isTree1HaveTree2(tree1.right, tree2.right);
    }
}

class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int x) {
        val = x;
    }

    //            10
    //         /      \
    //        6        14
    //       /\        /\
    //      4  8     12  16

    /**
     * 生成二叉搜索树
     *
     * @return
     */
    public static TreeNode generateBinaryTree() {
        TreeNode root = new TreeNode(10);
        TreeNode node6 = new TreeNode(6);
        TreeNode node14 = new TreeNode(14);
        TreeNode node4 = new TreeNode(4);
        TreeNode node8 = new TreeNode(8);
        TreeNode node12 = new TreeNode(12);
        TreeNode node16 = new TreeNode(16);
        connectNode(root, node6, node14);
        connectNode(node6, node4, node8);
        connectNode(node14, node12, node16);
        return root;
    }

    //        6
    //       /\
    //      4  8

    /**
     * 生成子树
     *
     * @return
     */
    public static TreeNode generateSubTree() {
        TreeNode node6 = new TreeNode(6);
        TreeNode node4 = new TreeNode(4);
        TreeNode node8 = new TreeNode(8);
        connectNode(node6, node4, node8);
        return node6;
    }

    private static void connectNode(TreeNode root, TreeNode left, TreeNode right) {
        root.left = left;
        root.right = right;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值