1. 通过CD170 判断t1树是否包含t2树全部的拓扑结构 改写即可,时间复杂度 O(n * m)
    代码如下:

    import java.util.Scanner;
    import java.util.List;
    import java.util.ArrayList;
    import java.util.Map;
    import java.util.HashMap;
    import java.util.Stack;
    class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
    
     public TreeNode(int val) {
         this.val = val;
     }
    }
    class ScannerInfo {
     int rootNum;
     int[][] info;
     public ScannerInfo(int rootNum, int[][] info) {
         this.rootNum = rootNum;
         this.info = info;
     }
    }
    public class Main {
     static Map<Integer,TreeNode> cache = new HashMap<>(16);
    
     public static void main(String[] args) {
         Scanner scanner = new Scanner(System.in);
         while(scanner.hasNext()) {
             ScannerInfo bigTreeScannerInfo = scannerInfo(scanner);
             TreeNode bigTree = constructTree(bigTreeScannerInfo.rootNum, bigTreeScannerInfo.info);
             ScannerInfo smallTreeScannerInfo = scannerInfo(scanner);
             TreeNode smallTree = constructTree(smallTreeScannerInfo.rootNum, smallTreeScannerInfo.info);
             System.out.printf("%s\n", String.valueOf(isSubTree(bigTree, smallTree)));
         }
     }
    
     private static boolean isSubTree(TreeNode big, TreeNode small) {
         boolean result1 = check(big, small);
         boolean result2 = check(big.left, small);
         boolean result3 = check(big.right,small);
         return result1 || result2 || result3;
     }
    
     private static boolean check(TreeNode big, TreeNode small) {
         if (big == null && small == null) {
             return true;
         }
         if (big == null || small == null) {
             return false;
         }
         if (big.val != small.val) {
             return check(big.left, small) || check(big.right,small);
         }
         return check(big.left, small.left) && check(big.right, small.right);
     }
    
     private static ScannerInfo scannerInfo(Scanner scanner) {
         int treeNum = scanner.nextInt();
         int treeRootNum = scanner.nextInt();
         int temp = treeNum;
         int i = 0;
         int[][] info = new int[treeNum][3];
         while(temp > 0) {
             info[i][0] = scanner.nextInt();
             info[i][1] = scanner.nextInt();
             info[i][2] = scanner.nextInt();
             i++;
             temp--;
         }
         ScannerInfo scannerInfo = new ScannerInfo(treeRootNum, info);
         return scannerInfo;
     }
    
     private static TreeNode constructTree(int rootNum, int[][] info) {
         cache = new HashMap<>();
         if (info == null || info.length == 0 || rootNum == 0) {
             return null;
         }
         for(int i = 0;i < info.length;i++) {
             TreeNode cur = getOrPutFromCache(info[i][0]);
             TreeNode left = getOrPutFromCache(info[i][1]);
             TreeNode right = getOrPutFromCache(info[i][2]);
             cur.left = left;
             cur.right = right;
         }
         return cache.get(rootNum);
    
     }
    
     private static TreeNode getOrPutFromCache(int num) {
         if (num == 0) {
             return null;
         }
         TreeNode result = cache.get(num);
         if (result == null) {
             result = new TreeNode(num);
             cache.put(num, result);
         }
    
         return result;
     }
    }
  2. 先序遍历序列化树,借助String的contains方法判断是否是子串,时间复杂度O(n+m)

    import java.util.Scanner;
    import java.util.List;
    import java.util.ArrayList;
    import java.util.Map;
    import java.util.HashMap;
    import java.util.Stack;
    class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
    
     public TreeNode(int val) {
         this.val = val;
     }
    }
    class ScannerInfo {
     int rootNum;
     int[][] info;
     public ScannerInfo(int rootNum, int[][] info) {
         this.rootNum = rootNum;
         this.info = info;
     }
    }
    public class Main {
     static Map<Integer,TreeNode> cache = new HashMap<>(16);
    
     public static void main(String[] args) {
         Scanner scanner = new Scanner(System.in);
         while(scanner.hasNext()) {
             ScannerInfo bigTreeScannerInfo = scannerInfo(scanner);
             TreeNode bigTree = constructTree(bigTreeScannerInfo.rootNum, bigTreeScannerInfo.info);
             ScannerInfo smallTreeScannerInfo = scannerInfo(scanner);
             TreeNode smallTree = constructTree(smallTreeScannerInfo.rootNum, smallTreeScannerInfo.info);
             String bigStr = preSerialize(bigTree);
             String smallStr = preSerialize(smallTree);
             boolean result = bigStr.contains(smallStr);
             System.out.printf("%s\n", String.valueOf(result));
         }
     }
    
     private static String preSerialize(TreeNode root) {
         if (root == null) {
             return "#!";
         }
         String res = root.val + "!";
         res += preSerialize(root.left);
         res += preSerialize(root.right);
         return res;
     }
     private static ScannerInfo scannerInfo(Scanner scanner) {
         int treeNum = scanner.nextInt();
         int treeRootNum = scanner.nextInt();
         int temp = treeNum;
         int i = 0;
         int[][] info = new int[treeNum][3];
         while(temp > 0) {
             info[i][0] = scanner.nextInt();
             info[i][1] = scanner.nextInt();
             info[i][2] = scanner.nextInt();
             i++;
             temp--;
         }
         ScannerInfo scannerInfo = new ScannerInfo(treeRootNum, info);
         return scannerInfo;
     }
    
     private static TreeNode constructTree(int rootNum, int[][] info) {
         cache = new HashMap<>();
         if (info == null || info.length == 0 || rootNum == 0) {
             return null;
         }
         for(int i = 0;i < info.length;i++) {
             TreeNode cur = getOrPutFromCache(info[i][0]);
             TreeNode left = getOrPutFromCache(info[i][1]);
             TreeNode right = getOrPutFromCache(info[i][2]);
             cur.left = left;
             cur.right = right;
         }
         return cache.get(rootNum);
    
     }
    
     private static TreeNode getOrPutFromCache(int num) {
         if (num == 0) {
             return null;
         }
         TreeNode result = cache.get(num);
         if (result == null) {
             result = new TreeNode(num);
             cache.put(num, result);
         }
    
         return result;
     }
    }
  1. 把String的contains替换成自己实现KMP算法

    import java.util.Scanner;
    import java.util.List;
    import java.util.ArrayList;
    import java.util.Map;
    import java.util.HashMap;
    import java.util.Stack;
    class TreeNode {
     int val;
     TreeNode left;
     TreeNode right;
    
     public TreeNode(int val) {
         this.val = val;
     }
    }
    class ScannerInfo {
     int rootNum;
     int[][] info;
     public ScannerInfo(int rootNum, int[][] info) {
         this.rootNum = rootNum;
         this.info = info;
     }
    }
    public class Main {
     static Map<Integer,TreeNode> cache = new HashMap<>(16);
    
     public static void main(String[] args) {
         Scanner scanner = new Scanner(System.in);
         while(scanner.hasNext()) {
             ScannerInfo bigTreeScannerInfo = scannerInfo(scanner);
             TreeNode bigTree = constructTree(bigTreeScannerInfo.rootNum, bigTreeScannerInfo.info);
             ScannerInfo smallTreeScannerInfo = scannerInfo(scanner);
             TreeNode smallTree = constructTree(smallTreeScannerInfo.rootNum, smallTreeScannerInfo.info);
             String bigStr = preSerialize(bigTree);
             String smallStr = preSerialize(smallTree);
             boolean result = getIndexOf(bigStr, smallStr) != -1;
             System.out.printf("%s\n", String.valueOf(result));
         }
     }
    
     private static int getIndexOf(String s, String m) {
         if (s == null || m == null || m.length() < 1 || s.length() < m.length()) {
             return -1;
         }
         char[] ss = s.toCharArray();
         char[] ms = m.toCharArray();
         int si = 0;
         int mi = 0;
         int[] next = getNextArray(ms);
         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;
     }
    
     private static int[] getNextArray(char[] ms) {
         if (ms.length == 1) {
             return new int[]{-1};
         }
         int[] next = new int[ms.length];
         next[0] = -1;
         next[1] = 0;
         int cn = 0;
         int pos = 2;
         while(pos < next.length) {
             if (ms[pos - 1] == ms[cn]) {
                 next[pos++] = ++cn;
             } else if (cn > 0) {
                 cn = next[cn];
             } else {
                 next[pos++] = 0;
             }
         }
         return next;
     }
    
     private static String preSerialize(TreeNode root) {
         if (root == null) {
             return "#!";
         }
         String res = root.val + "!";
         res += preSerialize(root.left);
         res += preSerialize(root.right);
         return res;
     }
    
     private static ScannerInfo scannerInfo(Scanner scanner) {
         int treeNum = scanner.nextInt();
         int treeRootNum = scanner.nextInt();
         int temp = treeNum;
         int i = 0;
         int[][] info = new int[treeNum][3];
         while(temp > 0) {
             info[i][0] = scanner.nextInt();
             info[i][1] = scanner.nextInt();
             info[i][2] = scanner.nextInt();
             i++;
             temp--;
         }
         ScannerInfo scannerInfo = new ScannerInfo(treeRootNum, info);
         return scannerInfo;
     }
    
     private static TreeNode constructTree(int rootNum, int[][] info) {
         cache = new HashMap<>();
         if (info == null || info.length == 0 || rootNum == 0) {
             return null;
         }
         for(int i = 0;i < info.length;i++) {
             TreeNode cur = getOrPutFromCache(info[i][0]);
             TreeNode left = getOrPutFromCache(info[i][1]);
             TreeNode right = getOrPutFromCache(info[i][2]);
             cur.left = left;
             cur.right = right;
         }
         return cache.get(rootNum);
    
     }
    
     private static TreeNode getOrPutFromCache(int num) {
         if (num == 0) {
             return null;
         }
         TreeNode result = cache.get(num);
         if (result == null) {
             result = new TreeNode(num);
             cache.put(num, result);
         }
    
         return result;
     }
    }