MaximumBinaryTree 最大二叉树

问题

拥有nn个节点的二叉树,节点范围为[1,n][1,n],节点ii的权值为正整数viv_i,整个二叉树的权值为所有节点的权值之和。现在要求只保留mm个节点(0<m<n10 \lt m \lt n-1),剪裁掉的节点数量为n1mn-1-m,要求剩余部分仍然是一个二叉树,而不能是多个二叉树。如图:

正确剪裁

错误剪裁

对于拥有nn个节点的二叉树,求出保留mm个节点的二叉树的最大权值。

解法

f(i,j)f(i,j)表示以节点ii为根节点的树上,保留jj个节点(包括节点ii自己)的最大权值。因此有转移方程如:

f(i,j)={vi(initialize)i[1,n],j=1max{f(lefti,k)+f(righti,j1k)+vi}(loop)i[1,n],j[2,n]f(i,j) = \begin{cases} v_i & (initialize) & i \in [1,n],j = 1 \\ max⁡\{ f(left_i,k)+f(right_i,j-1-k)+v_i \} & (loop) & i \in [1,n], j \in [2,n] \end{cases}

(1)(1) 节点数量为11的二叉树,其最大权值即为节点自己的权值,因此f(i,1)=vif(i,1) = v_i

(2)(2) 对于根节点为ii的二叉树,只留jj个节点。当左子树上有kk个节点(1kj11 \leq k \leq j-1),则右子树上有j1kj-1-k个节点,因为左右子树的节点数量之和为j1j - 1(根节点ii占一个节点)。设其左右孩子节点为leftileft_irightiright_i,左子树的最大权值为f(lefti,k)f(left_i,k),右子树的最大权值为f(righti,j1k)f(right_i,j-1-k),根节点的子树的最大权值为f(i)=f(lefti,k)+f(righti,j1k)+vif(i) = f(left_i, k) + f(right_i, j-1-k) + v_i。遍历k[1,j1]k \in [1, j-1],在所有可能中选取使f(i,j)f(i,j)最大的即可;

f(n,m)f(n,m)即为该二叉树留下mm个节点时的最大权值。该算法的时间复杂度是O(n×m)O(n \times m)

源码

MaximumBinaryTree.h

MaximumBinaryTree.cpp

测试

MaximumBinaryTreeTest.cpp

Last updated