树是另一棵树的子树吗?

时间:2015-03-12 20:04:00

标签: algorithm

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)); 
}

1 个答案:

答案 0 :(得分:3)

请考虑这个具体的例子:

T1

            1
           /
          1
         /
        1
       /
      1
     /
    1
   /
  1

T2

    1
   / \
  1   1

现在检查t1中是否包含t2。

毫无疑问,matchTree将在最后一步失败,并且t1将遍历整个树以找出它未被包含。

因此,在退化的树中,这将是最坏的情况,复杂性将是O(mn)。

更新:

如果两棵树是平衡的,但没有排序,唯一可以优化的是,我们知道当t1的子树短于t2时可以停止,即log(n) < log(m),所以复杂性可以

优化
O(2^(log(n)-log(m))*m) = O(n/m*m) = O(n)

UPDATE2:

如果它是已排序的,并且没有重复的元素,那么t2的根可以在O(log(n))中的t1中找到(如果存在),并且需要执行树遍历,即O(m)。所以它应该总结为O(log(n) + m)