Leetcode 2673. 使二叉树所有路径值想等的最小代价
给你一个整数 n 表示一棵 满二叉树 里面节点的数目,节点编号从 1 到 n 。根节点编号为 1 ,树中每个非叶子节点 i 都有两个孩子,分别是左孩子 2 * i 和右孩子 2 * i + 1 。
树中每个节点都有一个值,用下标从** 0** 开始、长度为 n 的整数数组 cost 表示,其中 cost[i] 是第 i + 1 个节点的值。每次操作,你可以将树中 任意 节点的值 增加 1 。你可以执行操作 任意 次。
你的目标是让根到每一个 叶子结点 的路径值相等。请你返回 最少 需要执行增加操作多少次。
注意:
- 满二叉树 指的是一棵树,它满足树中除了叶子节点外每个节点都恰好有 2 个子节点,且所有叶子节点距离根节点距离相同。
- 路径值 指的是路径上所有节点的值之和。
一种方法是遍历每一层,把每一层的数据都加到这一层的最大值,这样能实现根到每一个叶子节点的路径值相等。但是,会出现一种情况就是,另一棵子树的大值节点的值和小值节点的值加起来和中间值是相等的,也就是一个子树节点的值为 2,4,而另一棵子树对应层的值为 3,3。如果都加到最大值,结果为 3,但是它们本来就是相等的,结果应该为 0;
还有一种方法是计算每个叶子节点的路径值,最大的路径节点就是最终的目标,而其他小于最大值的差就是结果,这种过程只能把差值都加到叶子节点上,不然加到父结点就会出现不相等的情况。因此也不是满足要求的最小结果。
以上两种方法都是无法满足最小答案,先从叶子节点判断,同一父节点下的兄弟节点要想保证路径值相等,只能都加到最大值,那么这一父节点下的值就固定了,把最大值加到父节点下,就把父节点进化为叶子节点进行考虑。
这里要注意:在完全二叉树中节点编号是从 1 开始的,但是代价是从 0 开始的,要注意索引的变化。
完整代码
class Solution {
public int minIncrements(int n, int[] cost) {
int res = 0;
for (int i = n - 1; i > 0; i -= 2) {
res += Math.abs(cost[i - 1] - cost[i]);
cost[i / 2 - 1] += Math.max(cost[i - 1], cost[i]);
}
return res;
}
}