记录 1 道算法题
在二叉树中分配硬币
要求:二叉树每个节点都有 1 到 n 枚硬币,通过移动硬币,使二叉树每一个节点都分配 1 枚硬币,求最小移动次数。比如:[0,3,0]
,输出:3。
每一枚硬币的流向有方向,但路径是一样的。无论是计算从上往下还是下往上,都算作移动次数 + 1。所以我们可以假设没有硬币的节点流出了 -x 个硬币。有硬币的节点也流出了 -x 个硬币。由于当流动到某个节点输出 0 的时候,就代表均衡,每一个节点都有一枚硬币。最后一直回溯到根节点就可以知道硬币流动的路径,每一条路径算 1 次就能得到最小移动次数。
没有硬币的节点算流出 -1。
使用后序遍历解决
完整代码如下:
function distributeCoins(root) {
let res = 0
function f(node) {
if (!node) return 0
const l = f(node.left)
const r = f(node.right)
// 每次输出都作为移动了多少硬币,所以是绝对值
res += Math.abs(l) + Math.abs(r)
// 减去自身需要的 1 枚硬币,其他都作为流出
return node.val + l + r - 1
}
f(root)
return res
}