java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846
文章目录
1. 暴力求解,深度优先 2. KMP算法进行串匹配
1. 暴力求解,深度优先
解题思路:时间复杂度O(s*t)其中s是树的结点个数,t是子树的结点个数。空间复杂度O(max(ds,dt))其中ds是树的深度,dt是子树的深度
我们先对整个树深度优先遍历 每个结点都与子树的根节点进行比对 如果对上了,就以当前结点为根节点,进行和子树的深度优先遍历,看看是否一一对应 对应上就返回true,没对应上就继续深度优先遍历。直到整个树遍历完成
class Solution {
public boolean isSubtree ( TreeNode root, TreeNode subRoot) {
if ( root == null && subRoot == null ) return true ;
else if ( root == null || subRoot == null ) return false ;
else return isSubtree ( root. left, subRoot) || isSubtree ( root. right, subRoot) || isSameTree ( root, 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 isSameTree ( root. left, subRoot. left) && isSameTree ( root. right, subRoot. right) ;
}
return false ;
}
}
2. KMP算法进行串匹配
KMP算法https://blog.csdn.net/grd_java/article/details/136107363
解题思路:时间复杂度O(s+t),空间复杂度O(s+t)
生成两颗树的遍历序列,以类似如下的形式:(下面形式是广度(层序)遍历序列,需要额外空间辅助,所以我们放弃) 为了效率和更少的空间,我们使用广度优先遍历。那么就需要两个不同的值,来表示某结点左子树为空,和右子树为空的情况。 同样为了效率,我们不使用字符串比较,选用int型容器,比如int型的链表来生成匹配串 那么null如何来表示呢?
我们可以规定两个值,来分别表示左子树为null和右子树为null的情况 这里我选择先找到树中最大值max,然后令max+1表示左子树为空情况,max+2表示右子树为空情况
生成两颗树的匹配串后,让大树作为主字符串,要匹配的子树作为要匹配的子串,改编KMP算法,如果匹配成功,说明树中可以匹配到子树
代码:leetcode的特色之一就是,更优的算法,有时因为使用程序自带的特殊容器(比如Java中的List),因为这些容器初始化比较耗时间,反而耗时更高。但是实际工作场景,一旦数据量起来,肯定是这个算法优于上面的暴力解法的。
class Solution {
List < Integer > sOrder = new ArrayList < Integer > ( ) ;
List < Integer > tOrder = new ArrayList < Integer > ( ) ;
int maxElement, lNull, rNull;
public void getMaxElement ( TreeNode t) {
if ( t == null ) return ;
maxElement = Math . max ( maxElement, t. val) ;
getMaxElement ( t. left) ;
getMaxElement ( t. right) ;
}
public void getDfsOrder ( TreeNode t, List < Integer > tar) {
if ( t == null ) return ;
tar. add ( t. val) ;
if ( t. left != null ) getDfsOrder ( t. left, tar) ;
else tar. add ( lNull) ;
if ( t. right != null ) getDfsOrder ( t. right, tar) ;
else tar. add ( rNull) ;
}
public boolean isSubtree ( TreeNode s, TreeNode t) {
maxElement = Integer . MIN_VALUE ;
getMaxElement ( s) ;
getMaxElement ( t) ;
lNull = maxElement + 1 ;
rNull = maxElement + 2 ;
getDfsOrder ( s, sOrder) ;
getDfsOrder ( t, tOrder) ;
return kmp ( ) ;
}
public boolean kmp ( ) {
int sLen = sOrder. size ( ) , tLen = tOrder. size ( ) ;
int [ ] fail = new int [ tOrder. size ( ) ] ;
fail[ 0 ] = 0 ;
for ( int i = 1 , j = 0 ; i < tLen; ++ i) {
while ( j > 0 && ! ( tOrder. get ( i) . equals ( tOrder. get ( j) ) ) ) j = fail[ j- 1 ] ;
if ( tOrder. get ( i) . equals ( tOrder. get ( j) ) ) ++ j;
fail[ i] = j;
}
for ( int i = 0 , j = 0 ; i < sLen; ++ i) {
while ( j > 0 && ! ( sOrder. get ( i) . equals ( tOrder. get ( j) ) ) ) j = fail[ j- 1 ] ;
if ( sOrder. get ( i) . equals ( tOrder. get ( j) ) ) ++ j;
if ( j == tLen) return true ;
}
return false ;
}
}