LeetCode 545. Boundary of Binary Tree - 二叉树(Binary Tree)系列题12

You are given the root of a binary tree with n nodes where each node in the tree has node.val coins. There are n coins in total throughout the whole tree.

In one move, we may choose two adjacent nodes and move one coin from one node to another. A move may be from parent to child, or from child to parent.

Return the minimum number of moves required to make every node have exactly one coin.

Example 1:

Input: root = [3,0,0]
Output: 2
Explanation: From the root of the tree, we move one coin to its left child, and one coin to its right child.

Example 2:

Input: root = [0,3,0]
Output: 3
Explanation: From the left child of the root, we move two coins to the root [taking two moves]. Then, we move one coin from the root of the tree to the right child.

Constraints:

  • The number of nodes in the tree is n.
  • 1 <= n <= 100
  • 0 <= Node.val <= n
  • The sum of all Node.val is n.

题目给定一棵二叉树具有n个节点,每个节点值node.val表示该节点所拥有的硬币数。硬币总数为n,也就是说有的节点可能超过一枚硬币,有的节点可能没有硬币,现在要求通过移动硬币使得最后每个节点都刚好拥有一枚硬币。每次移动只能从一个节点移动到其相连的节点(父节点,左子节点或右子节点),并且一次只能移动一枚硬币。问最少需要移动几次可以使得每个节点都有一枚硬币?

为了使移动次数要最少,基本原则就是使移入或移出一个节点的硬币数要刚刚好。对于一个节点,它可以把整棵树分成2个部分:1)以该节点为根节点的子树;2)该节点的父节点以上的其它部分。经过该节点的进入或流出子树的硬币数,取决于子树里硬币的总数,如果硬币总数少于节点总数意味着要从外部输入硬币,反之如果硬币总数大于节点总数意味着有多余的硬币可以输出给其他地方使用。但是不管是输入还是输出,对于该节点来说都是硬币的移动。节点上多余或缺少的硬币数又由其自身加上左子树和右子树决定,假定左右子树多余或缺少硬币数分别为lcnt和rcnt(lcnt和rcnt为正表示有多余硬币,为负表示缺少硬币),另外节点本身始终需要一枚硬币,那么最终该节点上硬币数为node.val - 1 + lcnt + rcnt,也就是对于该节点最少移动次数。(值为负就去绝对值)。由于叶节点没有左右子树,一开始是否多余或缺少硬币就已经确定了,因此本可以通过递归从底向上计算每个节点上所需硬币数。

class Solution:
    def distributeCoins(self, root: Optional[TreeNode]) -> int:
        res = 0
        
        def helper(node):
            if not node:
                return 0
            
            lcnt = helper(node.left)
            rcnt = helper(node.right)
            
            cnt = node.val - 1 + lcnt + rcnt
            
            nonlocal res
            res += abs(cnt)
            
            return cnt
        
        helper(root)
        
        return res

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值