剑指offer16-树的子结构

判断一棵树是不是另一颗树的子树
首先可以先判断根节点是否相同,找到根节点相同的之后,再判断其左右子树是否相同。
当出现A树有某子节点,B树没有的时候,也有可能是true。
反之不行

public class Solution {
    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        if(root1==null || root2==null){
            return false;
        }
        if(root1.val == root2.val && isContain(root1,root2)){
            return true;
        }
        return HasSubtree(root1.left,root2) || HasSubtree(root1.right,root2);
    }
    
    public boolean isContain(TreeNode node1,TreeNode node2){
        if(node1 == null && node2!= null){
            return false;
        }
        if(node2 == null){
            return true;
        }
        return node1.val == node2.val && isContain(node1.left,node2.left) &&isContain(node1.right,node2.right);
    }
}

第二种方法:
首先先把两棵树进行序列化,化成字符串的形式(注意空子树要填#)
然后问题就转换成了求子串的问题。
用KMP算法来解这个问题。
时间复杂度比较小

    public boolean HasSubtree(TreeNode root1,TreeNode root2) {
        String a = serial(root1);
        String b = serial(root2);
        return getIndexOf(a,b);
    }
    //树的序列化
    public static String serial(TreeNode head){
        if(head == null){
            return "#";
        }
        String res = head.val+"";
        res += serial(head.left);
        res += serial(head.right);
        return res;
    }
    //准备用KMP算法判断一个是否是另一个的子串
    //先弄出Next数组
    public static int[] getNextArray(char[] ms){
        if(ms.length == 1){
            return new int[]{-1};
        }
        int[] nextArr = new int[ms.length];
        nextArr[0]=-1;
        nextArr[1]=0;
        int right = 2;
        int left = 0;
        while(right<nextArr.length){
            if(ms[right-1]==ms[left]){
                nextArr[right++] = ++left;
            }else if(left>0){
                left = nextArr[left];
            }else{
                nextArr[right++]=0;
            }
        }
        return nextArr;
    }
    
    //判断两个String是否是子串
    public static boolean getIndexOf(String s, String m) {
        if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
            return false;
        }
        char[] ss = s.toCharArray();
        char[] ms = m.toCharArray();
        int[] nextArr = getNextArray(ms);
        int index = 0;
        int mi = 0;
        while (index < ss.length && mi < ms.length) {
            if (ss[index] == ms[mi]) {
                index++;
                mi++;
            } else if (nextArr[mi] == -1) {
                index++;
            } else {
                mi = nextArr[mi];
            }
        }
        return mi == ms.length;
    }
}
在这里插入代码片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值