包含set中节点的最小子树

时间:2016-11-28 11:27:50

标签: algorithm tree subtree

有树结构,例如

   1
  / \
 /   \
2     3
|    / \
|   /   \
4  5     6

和必须在子树中的节点(叶子)集合,例如

[5, 6]

如何找到包含所有这些节点并从根元素开始的最小子树?像这样:

   1
    \
     \
      3
     / \
    /   \
   5     6

3 个答案:

答案 0 :(得分:2)

基本上,您可以递归到叶子,并找到每个叶子是否需要它。当递归再次返回时,您可以看到是否需要任何后代。

这是执行此操作的伪代码:

def mark_needed_nodes(node, given_nodes):
    # If a leaf, check if it is in given_nodes
    if node is leaf:
        node.needed = node in given_nodes
        return node.needed

    # It is not a leaf; check if any of the descendants is needed.
    node.needed = False
    for child in node.children:
        node.needed = needed or mark_needed_nodes(child, given_nodes)
    return node.needed

您可以致电mark_needed_nodes(root, given_nodes)

假设given_nodes是基于散列的字典,复杂性在树中的节点数是线性的。

答案 1 :(得分:1)

我认为,没有必要遍历整棵树。我们可以从每个给定的叶节点“直线”绘制直到根。

这样的事情:

  1. 根据需要标记根节点。
  2. 首先不处理给定的叶节点。如果没有,我们就完成了。
  3. 标记当前节点。
  4. 转到当前节点的父节点。
  5. 如果已经需要当前节点,请转到2,否则转到3.

答案 2 :(得分:0)

假设您的查询集中有k个节点,树中有n个节点。如果您需要在同一个树上执行许多查询,并且树比典型的查询集大得多,那么您可以考虑以下解决方案。

复杂的O(n) - 预处理时间,O(k) - 查询时间解决方案

您可以先preprocess your tree in linear time so that you can determine the lowest common ancestor of a pair of nodes in constant time。然后,对于给定的查询,您可以找到两个查询节点的最低共同祖先,然后查找该节点的最低共同祖先和查询中的第三个节点等,以确定您的所有节点的最低共同祖先。查询在O(k)时间整体设置。但是,预处理和查询都很复杂,除非您的树与查询大小相比很大,并且在同一个树上有许多单独的查询(因此预处理所花费的时间得到回报),这不太可能是最快的方式。 / p>