题目要求
给定一个有 N 个结点的二叉树的根结点 root,树中的每个结点上都对应有 node.val 枚硬币,并且总共有 N 枚硬币。
在一次移动中,我们可以选择两个相邻的结点,然后将一枚硬币从其中一个结点移动到另一个结点。(移动可以是从父结点到子结点,或者从子结点移动到父结点。)。
返回使每个结点上只有一枚硬币所需的移动次数。
示例 1:
输入:[3,0,0]
输出:2
解释:从树的根结点开始,我们将一枚硬币移到它的左子结点上,一枚硬币移到它的右子结点上。
示例 2:
输入:[0,3,0]
输出:3
解释:从根结点的左子结点开始,我们将两枚硬币移到根结点上 [移动两次]。然后,我们把一枚硬币从根结点移到右子结点上。
示例 3:
输入:[1,0,2]
输出:2
示例 4:
输入:[1,0,0,null,3]
输出:4
提示:
1<= N <= 1000 <= node.val <= N
解题思路
首先明确一点整个树最终形态是每个结点都是一枚金币。
然后将问题最小化(这也是递归和动态规划的思路),我们探讨三个结点的二叉树会出现什么情况
图例一
首先我们分析左结点值为3的结点它要成为1,它需要减去2。然后分析右结点值为0的结点它要成为0,它需要加上1。这时候就出现一个问题:根节点此时什么情况?在满足了左右结点后根节点其实就已经满足了要求。
现在开始程序设计,首先使用深度搜索来进行遍历节点,然后记录每个节点变成1所需要的步数。
class Solution(object):
move = 0
def distributeCoins(self, root):
def dfs(root):
moveleft = 0
moveright = 0
if root is None:
return 0
if root.left is not None:
moveleft = dfs(root.left)
if root.right is not None:
moveright = dfs(root.right)
self.move += abs(moveleft) + abs(moveright)
return moveleft + moveright + root.val - 1
dfs(root)
return self.move
上述程序中(return moveleft + moveright + root.val - 1)这句话是因为根要变成1所有要减去一个金币的值返回。
上述代码运行图例一的流程:
1、遍历根结点发现左节点不为空,进入左节点为根的树中。
2、发现此时以左结点为根的树中左右结点为空那么此时根节点需要一个金币一共所需要的步数为,当前的值3减去需要的一枚金币1,最后得出结果2,这就是左结点完成需求所需要的步数。
3、进入右结点,同理可得1步是右结点完成需求需要的步数。
4、此时左右结点完成需求所需要的步数为总共为3程序结束。