另一棵树的子树
- 另一棵树的子树
- 题目描述
- 解法一 DFS
- 解法二 KMP 算法
- KMP 算法
另一棵树的子树
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/subtree-of-another-tree
题目描述
给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在,返回 true ;否则,返回 false 。
二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所有后代节点。tree 也可以看做它自身的一棵子树。
示例1:
输入:root = [3,4,5,1,2], subRoot = [4,1,2]
输出:true
示例2:
输入:root = [3,4,5,1,2,null,null,null,null,0], subRoot = [4,1,2]
输出:false
提示:
root 树上的节点数量范围是 [1, 2000]
subRoot 树上的节点数量范围是 [1, 1000]
-104 <= root.val <= 10000
-104 <= subRoot.val <= 10000
解法一 DFS
深度优先搜索枚举 s 中的每一个节点,判断这个点的子树是否和 t 相等。如何判断一个节点的子树是否和 t 相等呢,我们又需要做一次深度优先搜索来检查,即让两个指针一开始先指向该节点和 t 的根,然后「同步移动」两根指针来「同步遍历」这两棵树,判断对应位置是否相等。
代码演示:
/**
* 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 s, TreeNode t) {
return dfs(s, t);
}
public boolean dfs(TreeNode s, TreeNode t){
if(s == null){
return false;
}
return check(s,t) || dfs(s.left,t) || dfs(s.right,t);
}
public boolean check(TreeNode s, TreeNode t){
if(s == null && t == null){
return true;
}
if(s == null || t == null || s.val != t.val){
return false;
}
return check(s.left,t.left) && check(s.right,t.right);
}
}
解法二 KMP 算法
我们先通过先序遍历,把先序遍历成两个字符串数组,通过KMP 算法里来判断一个字符串是否是其中另外一个的字串。
代码演示:
public static boolean isSubtree(TreeNode big, TreeNode small) {
if (small == null) {
return true;
}
if (big == null) {
return false;
}
ArrayList<String> b = preSerial(big);
ArrayList<String> s = preSerial(small);
String[] str = new String[b.size()];
for (int i = 0; i < str.length; i++) {
str[i] = b.get(i);
}
String[] match = new String[s.size()];
for (int i = 0; i < match.length; i++) {
match[i] = s.get(i);
}
return getIndexOf(str, match) != -1;
}
/**
* 前序序列化
* @param head
* @return
*/
public static ArrayList<String> preSerial(TreeNode head) {
ArrayList<String> ans = new ArrayList<>();
pres(head, ans);
return ans;
}
/**
* 前序遍历
* @param head
* @param ans
*/
public static void pres(TreeNode head, ArrayList<String> ans) {
if (head == null) {
ans.add(null);
} else {
ans.add(String.valueOf(head.val));
pres(head.left, ans);
pres(head.right, ans);
}
}
/**
* KMP 算法
* @param str1
* @param str2
* @return
*/
public static int getIndexOf(String[] str1, String[] str2) {
if (str1 == null || str2 == null || str1.length < 1 || str1.length < str2.length) {
return -1;
}
int x = 0;
int y = 0;
int[] next = getNextArray(str2);
while (x < str1.length && y < str2.length) {
if (isEqual(str1[x], str2[y])) {
x++;
y++;
} else if (next[y] == -1) {
x++;
} else {
y = next[y];
}
}
return y == str2.length ? x - y : -1;
}
/**
* 前缀数组
* @param ms
* @return
*/
public static int[] getNextArray(String[] ms) {
if (ms.length == 1) {
return new int[] { -1 };
}
int[] next = new int[ms.length];
next[0] = -1;
next[1] = 0;
int i = 2;
int cn = 0;
while (i < next.length) {
if (isEqual(ms[i - 1], ms[cn])) {
next[i++] = ++cn;
} else if (cn > 0) {
cn = next[cn];
} else {
next[i++] = 0;
}
}
return next;
}
/**
* 判断是否相等
* @param a
* @param b
* @return
*/
public static boolean isEqual(String a, String b) {
if (a == null && b == null) {
return true;
} else {
if (a == null || b == null) {
return false;
} else {
return a.equals(b);
}
}
}
KMP 算法
KMP–高效字符串匹配算法
Manacher算法 – 回文长度算法