给定一个仅由加减运算符和数字组成的二进制算术表达式树,如何尽可能地平衡树?任务是在不评估表达式的情况下平衡树,即节点数应保持不变。
示例:
+ +
/ \ / \
+ 15 >>>>>> - +
/ \ / \ / \
5 - 6 4 5 15
/ \
6 4
加法是可交换的和关联的,并且可以实现平衡。可交换性允许交换连续“ +”节点的子节点。关联性允许旋转。在上面的示例中,执行的转换可以视为
我正在考虑进行顺序遍历并首先平衡所有子树。我将尝试通过尝试所有可能的节点排列(其中只有12个)来平衡具有两个连续的“ +”节点的任何子树,以希望减少树的总高度。此方法应在任何步骤将树的高度最多减少1。但是,我无法确定是否总是会给出最小高度的树,尤其是当有两个以上连续的“ +”节点时。
另一种方法可能是将表达式树读入数组,然后用变量替换任何'-'子树。然后,我们由DP来确定括号的最佳位置。这必须自下而上完成,以便DP算法考虑任何'-'子树时都已经平衡。但是,我担心,因为可能有(n + 1)个!排列节点和括号的方法。当我在寻找O(n)算法时。
这是一个已知问题,是否有特定的解决方法?
答案 0 :(得分:3)
冒着做出类似“评估”之类的风险的风险(尽管我认为这不是),我将执行以下操作:
通过将否定标记传播到根,将整个树更改为加法节点。一种简单的方法是为每个叶节点添加一个“颜色”。节点的颜色可以在树行走期间直接计算。在遍历期间,您跟踪从-节点获取的右手链接的数量(或奇偶校验,因为这是我们感兴趣的唯一部分);当到达叶子时,如果奇偶校验为奇偶,则将其着色为绿色,如果奇偶校验为奇数,则为红色。 (否定了红叶。)在遍历过程中,-节点更改为 + 。
+ +
/ \ / \
+ 15 >>>>>> + 15
/ \ / \
5 - 5 +
/ \ / \
6 4 6 -4
现在,通过在叶的顶部构造最小深度的二叉树来最小化树的深度,按顺序对叶进行排序,而不考虑先前的树结构:
+ +
/ \ / \
+ 15 >>>>>> + +
/ \ / \ / \
5 + 5 6 -4 15
/ \
6 -4
将颜色转回到-节点。简单的变换是没有红色子代的节点(只需删除颜色)和只有一个红色子代和一个绿色子代的节点。后面的这些节点变成-节点;如果红色的孩子在左边,那么这些孩子也将倒过来。
棘手的情况是节点的所有子节点都是红色的。在这种情况下,向上移动树,直到找到具有绿色后代的父代。您找到的节点必须有两个子节点(否则,它的唯一子节点必须有一个绿色后代),其中一个孩子恰好具有绿色后代。然后,将该节点更改为-,如果右手后代的子代为绿色,则反转其子代,并为右手子代的所有(可能是新的)子代重新涂上绿色。
+ +
/ \ / \
+ + >>>>>> + -
/ \ / \ / \ / \
5 6 -4 15 5 6 15 4
也许值得指出的是,根节点的左侧有一个绿色后代,因为第一个叶节点是绿色的。这足以证明上述算法涵盖了所有情况。