📅  最后修改于: 2023-12-03 15:10:36.174000             🧑  作者: Mango
给定具有N
个结点的二叉树,要将此二叉树划分为两个集合,使两部分所有结点的子树之和的绝对差最小。返回此最小值。
示例:
输入:
5
/ \
2 6
/ \
1 9
输出:
1
解释:
将树分为两个子树: [5,2] 和 [6,1,9],他们的和分别为 7 和 16,使得他们之间的差的绝对值最小为 1。
对于一棵树,要将其分为两个集合,使得两部分所有结点的子树之和的绝对差最小,我们可以用动态规划来求解。
我们可以设dp[i][j]
表示前i
个结点,将其分为两个集合,其中一个集合的重量为j
时,两个集合的子树之和的最小差值。对于每个结点,我们可以选择将其放入第一个集合或第二个集合。
i
放入第一个集合,那么dp[i][j] = min(dp[i-1][j], dp[i-1][j-w[i]] + w[i])
,其中w[i]
表示结点i
的子树之和。i
放入第二个集合,那么dp[i][j] = min(dp[i-1][j], dp[i-1][j+w[i]] - w[i])
。最后,我们只需要在dp[N][ j]
中选出使|dp[N][j]|
最小的j
即可。
class Solution:
def minimumDifference(self, root: TreeNode) -> int:
def subtreeSum(node):
if not node:
return 0
return node.val + subtreeSum(node.left) + subtreeSum(node.right)
def dfs(node):
if not node:
return
l, r = node.left, node.right
dfs(l)
dfs(r)
for i in range(len(dp)):
dp[i] += (subtreeSum(l) if l else 0) - (subtreeSum(r) if r else 0)
if abs(dp[i]) < abs(dp[i] - 2 * sum_val): # 更新最小值
nonlocal res
res = abs(dp[i])
dp[i] = max(dp[i], dp[i] - 2 * sum_val) # 避免下一次循环重复减去
dp = [0] * 20001 # 因为子树之和最大为10000,所以默认为20000
sum_val = subtreeSum(root)
res = float('inf')
dfs(root)
return res
根据题目给出的数据范围,可以通过本题。