在二叉树中分配硬币
https://leetcode.cn/problems/distribute-coins-in-binary-tree/description/
描述
给定一个有 N 个结点的二叉树的根结点 root,树中的每个结点上都对应有 node.val
枚硬币,并且总共有 N 枚硬币。
在一次移动中,我们可以选择两个相邻的结点,然后将一枚硬币从其中一个结点移动到另一个结点。(移动可以是从父结点到子结点,或者从子结点移动到父结点。)。
返回使每个结点上只有一枚硬币所需的移动次数。
示例
思路
一般二叉树解法以递归居多,精髓就是大事化小小事化了。这道题可以先从三个节点看起,如同上面框框所示,节点123要想达成平衡,需要移动几次?节点2有2个金币,节点3有4个,所以达成平衡需要节点2向节点1移动1个金币,也就是2-1,节点3需要向节点1移动3个金币,也就是4-1。所以现在总共移动了**(2-1)+(4-1)=4次**。
次数有了,为什么减1也知道,因为它要留一个,那怎么求这个2和4呢?
很简单,2或4=左子节点给它的+右子节点给它的+本身有的,左子节点给它的=另一个(2-1)或(4-1),所以我们设递归的关键函数dfs=func(node *TreeNode) int
返回值就是这个(2-1)或(4-1)
dfs = func(node *TreeNode) int {var l, r intif node == nil {return 0}if node.Left != nil {l = dfs(node.Left)}if node.Right != nil {r = dfs(node.Right)}ans += abs(l) + abs(r) // 左右子节点可能是亏的 但是移动次数一定是正的return l + r + node.Val - 1}
最终代码如下
func distributeCoins(root *TreeNode) int {var ans intvar dfs func(node *TreeNode) intdfs = func(node *TreeNode) int {var l, r intif node == nil {return 0}if node.Left != nil {l = dfs(node.Left)}if node.Right != nil {r = dfs(node.Right)}ans += abs(l) + abs(r)return l + r + node.Val - 1}dfs(root)return ans
}func abs(i int) int {if i < 0 {return -i}return i
}