Problem: 572. 另一棵树的子树
文章目录
- 思路
- 解题方法
- 复杂度
- Code
思路
这个问题可以通过序列化树和KMP算法来解决。首先,我们将两棵树都序列化为一个字符串列表,然后使用KMP算法来检查第二棵树的序列化结果是否为第一棵树的子串。
解题方法
首先,我们定义一个序列化函数,将树的节点值按照前序遍历的顺序存储到一个列表中。对于空节点,我们将其表示为null。
然后,我们使用KMP算法来检查第二棵树的序列化结果是否为第一棵树的子串。KMP算法是一种高效的字符串匹配算法,它可以在O(n)的时间复杂度内完成匹配。
最后,我们返回KMP算法的结果,如果返回值不为-1,说明第二棵树是第一棵树的子树。
复杂度
时间复杂度:
O ( n + m ) O(n+m) O(n+m),其中n和m分别是两棵树的节点数。我们需要遍历两棵树的所有节点,并且在KMP算法中需要遍历两个字符串列表。
空间复杂度:
O ( n + m ) O(n+m) O(n+m),我们需要存储两棵树的序列化结果,以及KMP算法中的next数组。
Code
/*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* TreeNode() {}* TreeNode(int val) { this.val = val; }* TreeNode(int val, TreeNode left, TreeNode right) {* this.val = val;* this.left = left;* this.right = right;* }* }*/
class Solution {public boolean isSubtree(TreeNode t1, TreeNode t2) {if (t1 != null && t2 != null) {List<String> s1 = new ArrayList<>();List<String> s2 = new ArrayList<>();serial(t1, s1);serial(t2, s2);return kmp(s1, s2) != -1;}return t2 == null;}public int kmp(List<String> s1, List<String> s2) {int n = s1.size();int m = s2.size();int x = 0;int y = 0;int[] next = nextArray(s2, m);while (x < n && y < m) {if (isEquals(s1.get(x), s2.get(y))) {x++;y++;} else if (y == 0) {x++;} else {y = next[y];}}return y == m ? x - y : -1;}public int[] nextArray(List<String> s, int m) {if (m == 1) {return new int[] { -1 };}int[] next = new int[m];next[0] = -1;next[1] = 0;int i = 2, cn = 0;while (i < next.length) {if (isEquals(s.get(i - 1), s.get(cn))) {next[i++] = ++cn;} else if (cn > 0) {cn = next[cn];} else {next[i++] = 0;}}return next;}public void serial(TreeNode head, List<String> path) {if (head == null) {path.add(null);} else {path.add(String.valueOf(head.val));serial(head.left, path);serial(head.right, path);}}public boolean isEquals(String a, String b) {if (a == null && b == null) {return true;}if (a != null && b != null) {return a.equals(b);}return false;}
}