首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何计算二进制SubTree查找的空间复杂度

如何计算二进制SubTree查找的空间复杂度
EN

Stack Overflow用户
提问于 2015-06-07 04:49:33
回答 1查看 508关注 0票数 5

这个问题来自于“破解编码采访”一书。我很难理解解决方案的空间复杂性。

问题:

您有两个非常大的二叉树: T1 (数百万节点)和T2 (数百个节点)。创建一个算法来确定T2是否是T1的子树。

解决方案(用Java):

代码语言:javascript
复制
public static boolean containsTree(TreeNode t1, TreeNode t2) {
    if (t2 == null)
        return true; // The empty tree is a subtree of every tree.
    else
        return subTree(t1, t2);
}

/* Checks if the binary tree rooted at r1 contains the binary tree 
 * rooted at r2 as a subtree somewhere within it.
 */
public static boolean subTree(TreeNode r1, TreeNode r2) {
    if (r1 == null)
        return false; // big tree empty & subtree still not found.
    if (r1.data == r2.data) {
        if (matchTree(r1,r2)) return true;
    }
    return (subTree(r1.left, r2) || subTree(r1.right, r2)); 
}

/* Checks if the binary tree rooted at r1 contains the 
 * binary tree rooted at r2 as a subtree starting at r1.
 */
public static boolean matchTree(TreeNode r1, TreeNode r2) {
    if (r2 == null && r1 == null) 
        return true; // nothing left in the subtree
    if (r1 == null || r2 == null) 
        return false; //  big tree empty & subtree still not found
    if (r1.data != r2.data) 
        return false;  // data doesn’t match
    return (matchTree(r1.left, r2.left) && 
            matchTree(r1.right, r2.right));
}

书中说,这个解决方案的空间复杂度O(log(n) +log(m)),其中m是T1 (大树)中的节点数和T2中的n个节点数。

在我看来,似乎解决方案具有O( log(m) * log(n) )空间复杂性,因为“子树”函数具有log(N)递归调用,并且每个递归调用执行触发log(M)递归调用的"matchTree“函数。

为什么这个解决方案O(log(n) + log(m))的复杂性?

EN

回答 1

Stack Overflow用户

发布于 2015-06-07 05:50:15

由于我们没有在堆上创建任何对象,空间复杂性就是堆栈的大小。所以问题不是总调用发生了多少次,而是堆栈可以增长多大。

containsTree()只能调用subTree()subTree()可以调用自己或matchTree(),而matchTree()只能调用自己。因此,在调用matchTree()的任何地方,堆栈看起来都是这样的:

代码语言:javascript
复制
[containsTree] [subTree] ... [subTree] [matchTree] ... [matchTree]

这就是为什么在这里不增加空间复杂性的原因:每次对subTree()的调用都可以调用matchTree(),而对matchTree()的调用在subTree()继续递归之前离开堆栈。

按照“正确答案”的思路进行分析

如果问题没有具体说明树木是否平衡,那么一个真正最坏的分析就会认为它们可能不是。然而,你和这本书都是假设的。我们可以说T1的深度是c,T2的深度是d. c是O(log(m)),如果T1是平衡的,则可以把这个问题留到后面,而O(m)则不然。T2的d也是一样的。

matchTree()来说,最坏的情况是O(d),因为它能恢复的最远是T2的高度。

对于subTree()来说,最坏的情况是它的递归是O(c),因为它所能恢复的最大的是T1的高度,加上调用matchTree()的成本,总共是O(c+d)。

containsTree()只是在调用subTree()的基础上添加了一个常量,所以这不会改变空间复杂性。

因此,如果T1和T2都是平衡的,通过替换c和d,您可以看到O(log(m)+log(n))似乎是合理的。

关于“正确答案”的问题

就像我之前说过的,假设二叉树是平衡的,这是不对的,除非你知道它们是平衡的。因此,更好的答案可能是O(m+n)。

但是等等!问题是T2的大小小于T1的大小。这意味着n是O(m),log(n)是O(log(m))。所以我们为什么要浪费时间去担心

如果树是平衡的,空间复杂度就是O(log(m))。在一般情况下,你不知道什么是平衡的,真正的答案应该是O(m),大树的大小。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30690157

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档