运行 是时候检查一棵二叉树是否是另一棵二叉树的子树了

Running time to check if a binary tree is subtree of another binary tree

我遇到了一个 naive solution 检查二叉树是否是另一个二叉树的子树的问题:

给定两棵二叉树,检查第一棵树是否是第二棵树的子树。树T的子树是由T中的一个节点及其在T中的所有后代组成的树S。根节点对应的子树是整棵树;对应于任何其他节点的子树称为真子树。

例如,在下面的例子中,树S是树T的子树:

 Tree 2

      10  
    /    \ 
  4       6
   \
    30

    Tree 1
          26
        /   \
      10     3
    /    \     \
  4       6      3
   \
    30

解决方案是以预序方式遍历树T。对于遍历中的每一个访问过的节点,查看以该节点为根的子树是否与S相同。

在post中说该算法在最坏情况下有一个运行 n^2 或 O(m*n) 的时间,其中 m 和 n 是两者的大小涉及的树木。

这里的混淆点是,如果我们同时遍历两棵树,在最坏的情况下,您似乎只需要递归遍历较大树中的所有节点即可找到子树。那么这个版本的算法(不是this one)怎么会有二次运行时间呢?

为了合理优化求解,将两棵树展平。使用 Lisp 符号, 我们得到

(10 (4(30) (6))

(26 (10 (4(30) (6)) (3 (3))

所以子树是parent的子串。使用 strstr 我们可以 在 O(N) 时间内正常完成,可能需要更长的时间 如果我们有很多很多 sub-trees。您可以使用后缀 如果您需要进行大量搜索并将其降低到 O(M) 时间,其中 M 是子树的大小。

但实际上运行时间并没有提高。都是一样的算法 它将有 N M 个行为,例如,如果所有的树 具有相同的节点 ID 和结构,除了最后一个权利 child 的查询 sub-tree。只是操作 变得更快了。

嗯,基本上在 isSubTree() 函数中你只遍历 T 树(主树,不是子树)。您对 S 不执行任何操作,因此在最坏的情况下,将为 T 中的每个节点执行此函数。但是(在最坏的情况下)对于每次执行,它将检查是否 areIdentical(T, S),在最坏的情况下必须完全遍历其中一棵给定的树(直到其中一棵树的大小为零)。

传递给areIdentical()函数的树明显越来越小,但是这种情况下如果涉及到时间复杂度就无所谓了。无论哪种方式,这都会为您提供 O(n^2)O(n*m)(其中 nm - 这些树中的节点数)。