美文网首页TREE
572. Subtree of Another Tree

572. Subtree of Another Tree

作者: DrunkPian0 | 来源:发表于2017-05-09 12:20 被阅读70次

这是leetcode weekly contest31的第二题,easy题。要比较的是「子树」而非「子结构」。树的递归的题目不太好调试(其实也好调试的,就是testcase写起来麻烦)。

Editorial Solution里面提到三种approach:
Approach #1 Check All Subtrees [Accepted]
Approach #2 Using Preorder Traversal [Accepted]
Approach #3 By Comparison of Nodes [Accepted]

approach 3

我当时写的是第三种,先找到值相同的node,再比较这两个node是否代表相同的subtree。

Code:

    public boolean isSubtree(TreeNode s, TreeNode t) {
        //find node
        boolean res = false;
        if (s != null && t != null) {
            if (s.val == t.val) {
                res = checkSame(s, t);
            }
            if (!res) {
                res = isSubtree(s.left, t);
            }
            if (!res) {
                res = isSubtree(s.right, t);
            }
        }
        return res;
    }

    private boolean checkSame(TreeNode s, TreeNode t) {
        if (t == null && s == null) return true;
        if (t == null || s == null) return false;
        if (s.val != t.val) return false;
        return checkSame(s.left, t.left) && checkSame(s.right, t.right);
    }

还可以这样写:

    public boolean isSubtree(TreeNode s, TreeNode t) {
        return s != null && (checkSame(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t));
    }

    private boolean checkSame(TreeNode s, TreeNode t) {
        if (t == null && s == null) return true;
        if (s == null || t == null) return false;
        if (s.val != t.val) return false;
        return checkSame(s.left, t.left) && checkSame(s.right, t.right);
    }

错误的示范

isSubtree的部分可以有很多种写法,可以用上面的one-liner,但是不能这么写,能看出为什么吗:

    public boolean isSubtree(TreeNode s, TreeNode t) {
        if (s!=null){
            if (s.val == t.val) return checkSame(s , t );
            else return isSubtree(s.left , t) || isSubtree(s.right , t);
        }
        return false ;
//        return s != null && (checkSame(s, t) || isSubtree(s.left, t) || isSubtree(s.right, t));
    }

因为上面这段代码跟注释掉的1-liner相比,在找到两个相同的节点后并没有再去判断s的孩子是否还和t的value相同。相当于s.val和t.val跟后面的else是与的关系了而不是或的关系。[1,1][1]的test case过不了。

如果要判断是否是「子结构」而不是「子树」

如果要判断是否是「子结构」而不是「子树」 , checkSame这样写:

    private boolean checkSame(TreeNode s, TreeNode t) {
        if (t == null) return true ; 
        if (s == null) return false ;
        if (s.val != t.val) return false;
        return checkSame(s.left, t.left) && checkSame(s.right, t.right);
    }

递归真是博大精深。。

approach 1

遍历所有子树,加入到set里去,贴在下面:

public class Solution {
    HashSet<String> trees = new HashSet<>();
    public boolean isSubtree(TreeNode s, TreeNode t) {
        String tree = inorder(t);
        findAllSubTrees(s);
        return trees.contains(tree);
    }

    public String findAllSubTrees(TreeNode s) {
        if (s == null) {
            return "";
        }
        String val = findAllSubTrees(s.left) + s.val + findAllSubTrees(s.right);
        trees.add(val);
        return val;
    }

    public String inorder(TreeNode t) {
        if (t == null)
            return "";
        return inorder(t.left) + t.val + inorder(t.right);
    }
}

approach 2

traversal,用indexOf判断是不是substring。事实证明,用inorder也可以的。

public class Solution {
    HashSet < String > trees = new HashSet < > ();
    public boolean isSubtree(TreeNode s, TreeNode t) {
        String tree1 = preorder(s, true);
        String tree2 = preorder(t, true);
        System.out.println(tree1);
        System.out.println(tree2);
        return tree1.indexOf(tree2) >= 0;
    }
    public String preorder(TreeNode t, boolean left) {
        if (t == null) {
            if (left)
                return "lnull";
            else
                return "rnull";
        }
        return "#"+t.val + " " +preorder(t.left, true)+" " +preorder(t.right, false);
    }
}

相关文章

网友评论

    本文标题:572. Subtree of Another Tree

    本文链接:https://www.haomeiwen.com/subject/zsubtxtx.html