【问题标题】:Select the subtrees containing exactly K leaves选择恰好包含 K 个叶子的子树
【发布时间】:2012-11-19 15:22:22
【问题描述】:

我得到了一棵树 T,它有 n 节点和 l 叶子。

我必须选择一些正好包含k (<=l) 叶子的子树。如果我选择节点t的祖先的子树,我们不能选择t的子树。

例如:

这是树 T,它有 13 个节点(7 个叶子)。

如果我想选择 k = 4 叶子,我可以选择节点 4 和 6(或节点 2 和 5)。这是选择的最小数量。 (我们也可以选择节点 6、7、8、9,但这不是最小值)。

如果我想选择k = 5叶子,我可以选择节点3,这是选择的最小数量。

我想选择最少数量的子树。我只能找到O(nk^2)O(nk) 算法,它使用BFS 和动态编程。选择这个有更好的解决方案吗?

谢谢:)

【问题讨论】:

  • 你能举个简单的例子吗?我一直无法理解如何才能拥有最少的子树数。据我所知,你总是有固定数量的有 k 片叶子的树。
  • @Rubens 完成。感谢您的建议:)
  • 不客气!现在,您的问题变得足够紧凑,可以提供有趣的解决方案 ^^ 发生了,不过,我看不出比 O(nk) 更好的了。好问题,无论如何!

标签: algorithm tree


【解决方案1】:

实际上,要知道每个子树的叶子数,您只需要遍历每个节点一次,因此复杂度应该是O(nm) 其中m 是每个节点的平均子节点数,在大多数情况下计算为O(n),因为m 只是一个常数。为此,您应该:

  • 找出树的哪些节点是叶子
  • 上树,为每个节点保存其子树中的叶子数

您可以通过从叶子开始并将父母放入队列中来做到这一点。当您将节点n_i 从队列中弹出时,从n_i 的每个子节点开始,将每个子树中包含的叶子数相加。完成后,将n_i 标记为已访问(这样您就不会多次访问它,因为每个孩子可以添加一次)

这给出了这样的结果:

^
|               f (3)              This node last
|              / \
|            /     \
|          /         \
|        /             \
|       d (2)           e (1)      These nodes second
|      /  \            /
|     /    \          / 
|    a (1)  b (1)    c (1)         These nodes first

步骤如下:

Find leaves `a`, `b` and `c`.
For each leave, add parent to queue   # queue q = (d, d, e)

Pop d                                 # queue q = (d, e)
Count leaves in subtree: d.leaves = a.leaves + b.leaves
Mark d as visited
Add parent to queue                   # queue q = (d, e, f)

Pop d                                 # queue q = (e, f)
d is visited, do nothing

Pop e                                 # queue q = (f)
Count leaves in subtree: e.leaves = c.leaves
Mark d as visited
Add parent to tree                    # queue q = (f, f)

Pop f                                 # queue q = (f)
Count leaves in subtree: f.leaves = d.leaves + e.leaves
Mark d as visited
Add parent to tree (none)

Pop f                                 # queue q = ()
f is visited, do nothing

您还可以使用智能数据结构来忽略添加两次的节点。请注意,您不能使用有序集,因为在“较高”节点之前探索“较低”节点非常重要。

在您的情况下,如果队列中的节点超过 k 叶子,您可以消除它们,并返回您发现具有 k 叶子的每个节点,这将提供更快的算法。

【讨论】:

  • 我想我的问题有误。我添加了一个示例,您能提供更多建议吗?谢谢:)
猜你喜欢
  • 1970-01-01
  • 2011-03-17
  • 2019-08-09
  • 2018-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多