《程序员代码面试指南》第三章 二叉树问题 判断t1 树中是否有与t2 树拓扑结构完全相同的子树

题目

判断t1 树中是否有与t2 树拓扑结构完全相同的子树

java代码

package com.lizhouwei.chapter3;

/**
 * @Description: 判断t1 树中是否有与t2 树拓扑结构完全相同的子树
 * @Author: lizhouwei
 * @CreateDate: 2018/4/19 21:35
 * @Modify by:
 * @ModifyDate:
 */
public class Chapter3_12 {

    public boolean isSubTree(Node shead,Node mhead  ){
        String str1 =serialize(shead);
        String str2 =serialize(mhead);
        System.out.println("shead: "+str1);
        System.out.println("mhead: "+str2);

        int res = KMP(str1, str2);
        return res==-1?false:true;
    }
    //树的序列化
    public String serialize(Node head) {
        if (head == null) {
            return "#!";
        }
        String res = head.value + "!";
        res += serialize(head.left);
        res += serialize(head.right);
        return res;
    }

    //KMP
    public int KMP(String s, String m) {
        if (s == null || m == null || m.length() > s.length()) {
            return -1;
        }
        char[] ss = s.toCharArray();
        char[] ms = s.toCharArray();
        int[] next = getNext(ms);
        int si = 0;
        int mi = 0;
        while (si < ss.length && mi < ms.length) {
            if (ss[si] == ms[mi]) {
                si++;
                mi++;
            } else if (next[mi] == -1) {
                si++;
            } else {
                mi = next[mi];
            }
        }
        return mi == ms.length ? si - mi : -1;
    }

    public int[] getNext(char[] match) {
        int len = match.length;
        //next[i] 值为 {0,i-1}中,前缀子串和后缀子串 相等的最大长度
        int[] next = new int[len];
        //next[0] 前面没有元素,所以没有最大相等长度
        next[0] = -1;
        //next[1] 前面只有next[0]一个元素,
        // 由于前子串不能包含最后一个,后缀子串不能包含第一个,所以其值为 0 ;
        next[1] = 0;
        int pos = 2;
        // match[cn]表示  next[i-1]的最大前缀子串的后面一个字符,
        // 当i=2时,next[2-1]=0,说明 match[1]在{0,0}中没有前缀子串;
        //所以cn 从0 开始.
        //cn 既可以表示 i-1的前缀子串和后缀子串的最大长度。
        //也可表示 i-1的前缀子串的后面一个值得下标
        int cn = 0;
        while (pos < len) {
            if (match[pos - 1] == match[cn]) {
                next[pos++] = ++cn;
                //++cn后,cn表示pos的前缀子串和后缀子串的最大长度。
            } else if (cn > 0) {
                //表示i-1的前缀子串的后面一个值得下标
                cn = next[cn];
            } else {
                next[pos++] = 0;
            }
        }
        return next;
    }

    //测试
    public static void main(String[] args) {
        Chapter3_12 chapter = new Chapter3_12();
        Node head1 = new Node(1);
        head1.left = new Node(2);
        head1.right = new Node(3);
        head1.left.left = new Node(4);
        head1.left.right = new Node(5);

        head1.right.left = new Node(6);
        head1.right.right = new Node(7);

        head1.left.left.right = new Node(8);
        head1.left.right.left = new Node(9);
         Node head2 = new Node(2);
        head2.left = new Node(4);
        head2.right = new Node(5);
        head2.left.right = new Node(8);
        head2.right.left = new Node(9);

        Node head3 = new Node(2);
        head3.left = new Node(4);
        head3.right = new Node(5);
        head3.left.right = new Node(8);
         System.out.println("head1 是否包含head2 :" + chapter.isSubTree(head1, head2));
        System.out.println("head1 是否包含head3 :" + chapter.isSubTree(head1, head3));
    }
}


人生四大悲剧:穷的没钱做坏事,熟的没法做情侣,饿的不知吃什么,困得就是睡不着!

posted @ 2018-04-19 23:10  lizhouwei  阅读(519)  评论(0编辑  收藏  举报