LeetCode-572. Subtree of Another Tree (Java)

Given two non-empty binary trees s and t, check whether tree t has exactly the same structure and node values with a subtree of s. A subtree of s is a tree consists of a node in s and all of this node's descendants. The tree s could also be considered as a subtree of itself.

Example 1:
Given tree s:

     3
    / \
   4   5
  / \
 1   2
Given tree t:
   4 
  / \
 1   2
Return  true , because t has the same structure and node values with a subtree of s.

Example 2:
Given tree s:

     3
    / \
   4   5
  / \
 1   2
    /
   0
Given tree t:
   4
  / \
 1   2
Return  false .

--------------------------------------------------------------------------------------------------------------------------------

题意

求一个二叉树t是否是另一个二叉树s的子树,一个s子树由s中的一个节点以及这个节点的所有的后代组成。

思路

我的思路是:从s中节点值等于t的根节点值开始,遍历判断s的节点值与t的节点值是否相同,判断t的左或右孩子为空时,

s的左或右孩子情况,判断s的左或右孩子为空时,t的左右孩子情况。最终,测试用例只通过154个,并未全部通过。

其实,有另一种更简单、清晰的思路,就是遍历二叉树s和t,然后将他们的值拼接起来,最后再判断字符串是否包含t即可,

需要注意,这种方法需要在节点为空的时候添加具有标识的特殊字符,以便在具有相同树遍历方法的情况下,确定结构是否相同。

代码

public class Solution {
 public boolean isSubtree(TreeNode s, TreeNode t) {
        String spreorder = generatepreorderString(s); 
        String tpreorder = generatepreorderString(t);
        
        return spreorder.contains(tpreorder) ;
    }
    public String generatepreorderString(TreeNode s){
        StringBuilder sb = new StringBuilder();
        Stack<TreeNode> stacktree = new Stack();
        stacktree.push(s);
        while(!stacktree.isEmpty()){
           TreeNode popelem = stacktree.pop();
           if(popelem==null)
              sb.append(",#"); // Appending # inorder to handle same values but not subtree cases
           else      
              sb.append(","+popelem.val);
           if(popelem!=null){
                stacktree.push(popelem.right);    
                stacktree.push(popelem.left);  
           }
        }
        return sb.toString();
    }
}
这种方法号是比较长。

还有一种耗时比较短的方法:

private static boolean isSubtree(TreeNode s, TreeNode t, boolean isRoot) {
	//如果节点s和节点t都为空,则返回true
        if (s == null && t == null) return true;
        //如果节点s和t,有一个为空,另一个不为空,则返回false;
        else if (s == null || t == null) return false;
        //前两个if判断是根据树的结构进行判断,下面是在结构相同的前提下,判断节点的值是否相同
        else {
            //如果相同
            if (s.val == t.val) {
            	//则递归继续进行判断,如果左子树和右子树都判断完了,并且都返回的true,则返回true。
                if (isSubtree(s.left, t.left, true) && isSubtree(s.right, t.right, true)) return true;
            } else {
            	//如果节点的值不相同,如果已经开始判断是否为子树,则返回false
                if (isRoot) return false;
            }
            //如果s的左右孩子节点值与t的根节点值不同,则继续用s的左右孩子与t的根节点值比较。
            //isRoot是用来判断是否开始对其子树进行判断。
            为什么用或,因为t子树有可能在s的左子树或右子树。
            return isSubtree(s.left, t, isRoot) || isSubtree(s.right, t, isRoot);
        }        
    }

其实这个方法的思路和我的思路差不多,区别就是该方法的实现更合理。

首先,该方法有递归进行左右子树判断,而我是用非递归前序的遍历方法,而且我的方法用了三个stack,一个用于保存s,一个用于保存t,另一个用于保存当s的节点值等于t的根节点值时s的节点。而上面那个方法用一个标志位isRoot替代了我第三个stack的作用。其他对结果情况判断方面,我的方法和上面的方法是一致的。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值