目录链接:
力扣编程题-解法汇总_分享+记录-CSDN博客
GitHub同步刷题项目:
https://github.com/September26/java-algorithms
原题链接:力扣
描述:
给定一个有 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 <= 100
0 <= node.val <= N
解题思路:
* 解题思路:
* 其实这道题和平衡二叉树很像。
* 我们构建两颗树,
* 第一颗树numMap,记录每个节点及其子节点应该有多少个硬币。
* 第二颗树sumMap,记录每个节点及其子节点当前有多少个硬币。
* 每个节点当前具有的,减去应该具有的硬币数量,其差值的绝对值就是每个节点应该送出或者接受的数量。
* 求这个差值的和就是我们想要的结果。
代码:
class Solution979
{
public:int getTreeNodeNum(TreeNode *node, std::map<TreeNode *, int> &numMap){if (node == nullptr){return 0;}int num = 1;num += getTreeNodeNum(node->left, numMap);num += getTreeNodeNum(node->right, numMap);numMap[node] = num;return num;}int getTreeNodeSum(TreeNode *node, std::map<TreeNode *, int> &sumMap){if (node == nullptr){return 0;}int sum = node->val;sum += getTreeNodeSum(node->left, sumMap);sum += getTreeNodeSum(node->right, sumMap);sumMap[node] = sum;return sum;}int distributeCoins(TreeNode *root){int sum = 0;std::map<TreeNode *, int> numMap;std::map<TreeNode *, int> sumMap;getTreeNodeNum(root, numMap);getTreeNodeSum(root, sumMap);// std::cout << "Value: " << sumMap.size() << std::endl;int result = 0;for (auto it = numMap.begin(); it != numMap.end(); ++it){int sum = sumMap[it->first];int num = it->second;result += abs(sum - num);}return result;}
};