给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。
    二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。

    示例 1:
    输入:root = [3,4,5,1,2], subRoot = [4,1,2]

    1. 3
    2. / \
    3. 4 5
    4. / \
    5. 1 2
    6. 4
    7. / \
    8. 1 2

    输出:true

    示例 2:
    输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]

    1. 3
    2. / \
    3. 4 5
    4. / \
    5. 1 2
    6. /
    7. 0
    8. 4
    9. / \
    10. 1 2

    输出:false

    结合深度优先递归遍历的算法框架:
    当 root 节点的值和 subRoot 节点的值开始相等的时候可以开始判断

    1. boolean isSubtree = false;
    2. public boolean isSubtree(TreeNode root, TreeNode subRoot) {
    3. order(root, subRoot);
    4. return isSubtree;
    5. }
    6. public void order(TreeNode root, TreeNode subRoot) {
    7. if (root == null) {
    8. return;
    9. }
    10. if (root.val == subRoot.val) {
    11. isSubtree = ?
    12. } else {
    13. order(root.left, subRoot);
    14. order(root.right, subRoot);
    15. }
    16. }

    当 root 节点的值和 subRoot 节点的值相等时此时可以看成判断两棵树是否相同,可以参考 LeetCode 100. 相同的树:

    1. public boolean isSameTree(TreeNode p, TreeNode q) {
    2. if (p == null && q == null) {
    3. return true;
    4. }
    5. if (p != null && q != null && p.val == q.val) {
    6. return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    7. }
    8. return false;
    9. }

    完整算法:

    1. boolean isSubtree = false;
    2. public boolean isSubtree(TreeNode root, TreeNode subRoot) {
    3. order(root, subRoot);
    4. return isSubtree;
    5. }
    6. private void order(TreeNode root, TreeNode subRoot) {
    7. if (root == null) {
    8. return;
    9. }
    10. if (root.val == subRoot.val) {
    11. isSubtree = isSameTree(root, subRoot);
    12. } else {
    13. order(root.left, subRoot);
    14. order(root.right, subRoot);
    15. }
    16. }
    17. private boolean isSameTree(TreeNode p, TreeNode q) {
    18. if (p == null && q == null) {
    19. return true;
    20. }
    21. if (p != null && q != null && p.val == q.val) {
    22. return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    23. }
    24. return false;
    25. }

    提交后,测试用例未通过:
    输入:root = [1,1], subRoot = [1]
    测试结果:false
    期望结果:true

    说明思路有问题,只判断一次 root.val == subRoot.val 是不够的,应当需要不断的遍历 root 树,不断比较 root 的子树是否和 subRoot 树一致:

    1. public boolean isSubtree(TreeNode root, TreeNode subRoot) {
    2. boolean rootIsSame = isSameTree(root,subRoot);
    3. boolean leftIsSame = isSubtree(root.left, subRoot);
    4. boolean rightIsSame = isSubtree(root.right, subRoot);
    5. return rootIsSame || leftIsSame || rightIsSame;
    6. }
    7. private boolean isSameTree(TreeNode p, TreeNode q) {
    8. if (p == null && q == null) {
    9. return true;
    10. }
    11. if (p != null && q != null && p.val == q.val) {
    12. return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    13. }
    14. return false;
    15. }

    补全参数有效性检查

    1. public boolean isSubtree(TreeNode root, TreeNode subRoot) {
    2. if (subRoot == null) {
    3. // subRoot 为 null 一定都是 true
    4. return true;
    5. }
    6. if (root == null) {
    7. // subRoot 一定不为 null, 只要 root 为 null,肯定是 false
    8. return false;
    9. }
    10. boolean rootIsSame = isSameTree(root,subRoot);
    11. boolean leftIsSame = isSubtree(root.left, subRoot);
    12. boolean rightIsSame = isSubtree(root.right, subRoot);
    13. return rootIsSame || leftIsSame || rightIsSame;
    14. }
    15. private boolean isSameTree(TreeNode p, TreeNode q) {
    16. if (p == null && q == null) {
    17. return true;
    18. }
    19. if (p != null && q != null && p.val == q.val) {
    20. return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
    21. }
    22. return false;
    23. }