从Lakmann:查找树是否是另一个树的子树: 作者说解决方案(下面再现)是O(log(n)+ log(m))内存,其中n和m是每棵树的相应节点数。我无法弄清楚为什么会这样。有什么指针吗?
boolean containsTree(TreeNode t1, TreeNode t2){
if (t2 == null){
return true;
}
return subTree(t1, t2);
}
boolean subTree(TreeNode r1, TreeNode r2){
if (r1 == null){
return false;
}
if (r1.data == r2.data){
if (matchTree(r1, r2)){
return true;
}
}
return (subTree(r1.left, r2) || subTree(r1.right, r2));
}
boolean matchTree(TreeNode r1, TreeNode r2){
if (r2 == null && r1 == null){
return true;
}
if (r1 == null || r2 == null){
return false;
}
if (r1.data != r2.data){
return false;
}
return (matchTree(r1.left, r2.left) && matchTree(r1.right, r2.right));
}
答案 0 :(得分:3)
请考虑这个具体的例子:
T1
1
/
1
/
1
/
1
/
1
/
1
T2
1
/ \
1 1
现在检查t1中是否包含t2。
毫无疑问,matchTree
将在最后一步失败,并且t1将遍历整个树以找出它未被包含。
如果两棵树是平衡的,但没有排序,唯一可以优化的是,我们知道当t1的子树短于t2时可以停止,即log(n) < log(m)
,所以复杂性可以
O(2^(log(n)-log(m))*m) = O(n/m*m) = O(n)
如果它是已排序的,并且没有重复的元素,那么t2的根可以在O(log(n))
中的t1中找到(如果存在),并且需要执行树遍历,即O(m)
。所以它应该总结为O(log(n) + m)
。