leetcode刷题 572. 另一棵树的子树,Easy (Java)DFS&暴力+DFS&KMP
1.题目描述
给你两棵二叉树 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 <= 104
- -104 <= subRoot.val <= 104
来源:力扣(LeetCode)
链接:572. 另一棵树的子树
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2.题解
2.1 DFS&暴力(深度优先搜索)
2.1.1 思路
写了比题解简洁的递归,因为递归层数减少了,执行速度也比题解的答案快很多。
- 一个是
isSubtree
函数,也就是判断是否为子树。首先如果子树为空肯定为子树;其次如果根为空,那说明根的层数比子树浅,所以不为子树;最后判断目标子树是否为根的子树以及根的左右子树是否有目标子树。 - 还有一个
isSametree
函数,也就是判断这两棵树是否相等。先排除两者都为空;如果有一者为空,那么肯定不相同;最后判断值。如果值相同则可以判断左右子树是否相同。
tips:需要关注返回值中的且和或,子树是其中有一者为子树就为真,所以用或;而相同需要左右子树相同,所以要用且。
2.1.2 Java代码
class Solution {
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(subRoot == null){
return true;
}
if(root == null){
return false;
}
return isSametree(root,subRoot)||isSubtree(root.left,subRoot)||isSubtree(root.right,subRoot);
}
public boolean isSametree(TreeNode root,TreeNode subRoot){
if(root == null &&subRoot == null){
return true;
}
if(root == null || subRoot == null){
return false;
}
if(root.val != subRoot.val){
return false;
}
return isSametree(root.right,subRoot.right)&&isSametree(root.left,subRoot.left);
}
}
2.2 DFS&KMP
2.2.1 思路
是因为树的先序遍历是按照顺序的,所以可以将树的结构改成数组的结构,然后通过KMP来实现数组的对比。
对KMP不了解的可以看,字符串匹配和KMP.
就通过root树和所求的子树通过DFS形成一个先序的数组,之后通过KMP进行对比。如果其中有子数组则返回true;反之则为false。
2.2.2 Java代码
class Solution {
List<Integer> rootOrder = new ArrayList<>();
List<Integer> subRootOrder = new ArrayList<>();
int leftNull = 100001,rightNull = 100002;
public boolean isSubtree(TreeNode root, TreeNode subRoot) {
if(root == null){
return false;
}
makeOrder(root,rootOrder);
makeOrder(subRoot,subRootOrder);
return kmp(rootOrder,subRootOrder);
}
public void makeOrder(TreeNode tree,List<Integer> order){
if(tree == null){
return;
}
order.add(tree.val);
if(tree.left != null){
makeOrder(tree.left,order);
}
else{
order.add(leftNull);
}
if(tree.right != null){
makeOrder(tree.right,order);
}
else{
order.add(rightNull);
}
}
public boolean kmp(List<Integer> rootO,List<Integer> subRootO){
int n = rootO.size(),m = subRootO.size();
int[] prefix = new int[m];
for(int i =1,j=0;i<m;i++){
while(j>0&&!subRootO.get(i).equals(subRootO.get(j))){
j = prefix[j-1];
}
if(subRootO.get(i).equals(subRootO.get(j))){
j++;
}
prefix[i] = j;
}
for(int i =0,j=0;i<n;i++){
while(j>0&&!rootO.get(i).equals(subRootO.get(j))){
j = prefix[j-1];
}
if(rootO.get(i).equals(subRootO.get(j))){
j++;
}
if(j==m){
return true;
}
}
return false;
}
}