给出二叉树。我们必须remove an edge
并将其划分为two trees
,以便difference of the diameter of the two new trees is less than a specified value K
。
我有一个天真的解决方案,选择each edge
并检查条件,如果通过删除该边缘我们可以获得解决方案(我们可以通过使用两个DFS/BFS
来计算直径)。这使我的解决方案O(n ^ 2)。
有人可以建议我采用比我更好的方法吗?
我认为我们可以使用动态编程,但我无法将其可视化。
答案 0 :(得分:0)
每个节点足以计算它下面树的高度。对于叶节点,它为0,对于其他节点,它为max(height of children) + 1
。这是通过tree post-order traversing完成的。
二叉树的直径为 height of left child + height of right child + 1
。对于一般树,它是(sum of two max heights) + 1
。
算法的想法是从根开始并“爬下”更高的孩子,同时检查孩子的子树的直径和树的其余部分之间的差异。这可以通过计算的高度来完成。
<强>更新强>
root
/ \
L R
在树中,直径通过根节点,或者完全在子树之一中。有了这个:
root.diameter = max(L.height + R.height + 2, L.diameter, R.diameter)
。
如果我们削减一些优势,例如N
和N.L
之间的边缘:
root
/ \
... ...
|
N
/ \
L R
L
子树具有上部公式的直径。其余的树有直径
max(R.height + length(R, root) + root.height, root.R.diameter, R.diameter)
。
条款R.height
和R.diameter
取决于我们要检查的优势。当我们检查root.height
子树(和反之)的边缘时,术语root.R.diameter
和root.L
是静态的。术语length(R, root)
取决于根的边缘深度,这很容易跟踪。
使用它可以创建递归检查一个子树边上的剪切的方法。