Maximum Binary Tree Merge - 最大二叉树合并


问题

拥有 n 个节点的二叉树,按照中序遍历将所有节点标记为 [1,n] ,如图:

MaximumBinaryTreeMerge1.svg

节点 i 拥有价值 vi ,将子树进行合并,产生的代价的计算方法是 v{tree} = v{leftChild} \times v{rightChild} + v_{root} ,即其左子树的合并代价乘以右子树的合并代价,再加根节点自身的价值,特别的我们规定空子树的合并代价为 1 。合并顺序的不同会使最终整个树的合并代价不同,求该二叉树的最大合并代价。

本问题的原型为“加分二叉树”。

解法

将二叉树中的所有节点按照中序遍历依次编号为 [1,n] ,根据中序遍历的性质,可知连续节点 [i,j] 刚好属于 1 个子树,且在 [i,j] 中选取节点 k 作为根节点( i \lt k \lt j ),则其左子树为 [i,k-1] ,右子树范围为 [k+1,j] 。例如上图中, [1,3] 属于子树 2 (以 2 为根节点的子树), [5,7] 属于子树 6 。设 f(i,j) 为以节点 [i,j] 组成的子树的最大合并代价,其中 i,j \in [1,n] j \leq i ,其转移方程如下:


f(i,j) =
\begin{cases}
1 & (初始化)i,j \in [0,n] \
1 \times 1+v_i & (初始化)i,j \in [1,n],i = j \
max { f(i,k-1) \times f(k+1,j) }+v_k & i,j,k \in [1,n],i \lt k \lt j
\end{cases}

(1) 将所有可能情况都初始化为最小的合并代价,即 1

(2) 对于只有一个节点的子树来说,其合并代价为自身根节点的价值加 1 ,即 f(i,i) = 1+v_i ,因为左右子树都是空子树,其合并代价为 1

(3) f(i,j) 分为 f(i,k-1) f(k+1,j) 左右两个子树,则 f(i,j) = f(i,k-1) \times f(k+1,j)+v_k ,其中 i \lt k \lt j 。在 [i,j] 范围内遍历所有情况,选取最大的即可;

f(1,n) 即为二叉树的最大合并价值。该算法的时间复杂度是 O(n^2)


加分二叉树


源码

import, lang:”c_cpp”

测试

import, lang:”c_cpp”