979. Distribute Coins in Binary Tree

只需要计算移动次数,因此硬币移动的顺序无关紧要(不然的话这个方法可能会遇到移动过程中 val<0 的情况),这一点帮助简化了问题。

针对每个node,我们都去考虑让它的左右子树分别满足要求,我们可以从当前node(父节点)获取或发送必要数量的硬币以首先平衡两个子树。因此考虑在这里使用DFS,以平衡每个子树并汇总移动次数move

以及如何计算当前子树的余额和移动次数?

到叶节点为止,使每个节点的余额为node.val - 1(节点本身需要一个硬币)。然后,我们需要从父节点向其收取相应的硬币(或发送,即余额为负值),并且每个硬币的移动成本为1,因此移动总成本为abs(余额)。

那么对于每一个节点,我们有两子树的余额,以及该node用来保持自身平衡的移动次数,这样该节点的余额是等于左节点的余额+右节点的余额+根节点的余额=left+right+node.val-1。由于我们总是使当前节点平衡,所以在计算全局移动次数的时候,只要一直计算左右子树移动成本即可,节点本身不计入。

返回的总移动成本move一开始写成了全局变量,显得有点累赘,后来改成了recursive传递。

class Solution:
    move = 0
    
    def postorder(self, node):
        if not node: return 0
        left = self.postorder(node.left)
        right = self.postorder(node.right)
        self.move += abs(left) + abs(right)
        return (node.val - 1 + left + right)
    
    def distributeCoins(self, root: TreeNode) -> int:        
        self.postorder(root)
        return self.move

Last updated

Was this helpful?