【LeetCode】979. Distribute Coins in Binary Tree 解题报告(C++)
作者: 负雪明烛
id: fuxuemingzhu
个人博客: http://fuxuemingzhu.cn/
题目地址:https://leetcode.com/problems/distribute-coins-in-binary-tree/
题目描述
Given the root of a binary tree with N nodes, each node in the tree has node.val coins, and there are N coins total.
In one move, we may choose two adjacent nodes and move one coin from one node to another. (The move may be from parent to child, or from child to parent.)
Return the number of moves required to make every node have exactly one coin.
Example 1:

Input: [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: [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.
Example 3:

Input: [1,0,2]
Output: 2
Example 4:

Input: [1,0,0,null,3]
Output: 4
Note:
- 1<= N <= 100
- 0 <= node.val <= N
题目大意
题目给出了一个二叉树,每个节点都有个数字代表当前节点有多少个金币,保证所有节点的金币数量之和等于节点个数。现在要求把金币平分到每个节点,使得每个节点都只放1个金币。问需要的移动次数是多少?
解题方法
递归
看到二叉树的题目我们一般想到递归,这个题也是如此。这个题是个难的的好题,确实很新颖。
首先,给定了一个二叉树的状态,只要不做重复移动,那么可以证明,移动是无状态的。也就是说,最终的移动次数不会因为先给谁后给谁,或者先移动几个再移动几个,再或者把某些金币移动到近的节点把另外一些金币移动到远的节点而有所不同。总之,我们可以放心大胆地,把金币移动到位,而不需要考虑把具体地金币移动到哪个确切的位置。
所以,我的思路就是分别统计左右子树缺少的金币个数,然后把每个节点和其子树总体的金币分配到位。累计所有节点和其子树所需要的移动次数就是结果。
每个子树缺少的金币数,等于节点数 - 金币数。因为题目确保了所有金币的和等于所有节点数,所以左子树缺少的金币数+该节点缺少的金币数+右子树缺少的金币数=0.我们每次把每个节点和其子树搞平衡,即左子树、该节点、右子树的节点数都等于金币数。注意此时,虽然左右子树总的不缺金币,但是内部仍然分配不均。所以,记录把这个节点搞平衡需要移动的金币数,然后累加上左子树和右子树搞平衡需要移动的金币数即为所求。
下面考虑,如果知道了左右子树需要的金币数,将他们搞平衡需要多少移动步数?答案是左右子树需要的金币数的绝对种子和。这个怎么理解?其实就是需要把子树多的金币挪给根节点,然后再从根节点分配给另一个缺少金币的子树对应的金币。举个栗子:

对于上面的树,左子树缺少-2个金币,右子树缺少1个金币。所以先把左子树多的那两个金币移动到根节点,然后根节点再给右子树分配缺的1个金币即可。因此总的移动次数是左右子树缺少的金币的和。
具体到代码,我们需要一个统计某个子树需要多少金币的函数need();需要计算把自身,左右子树都平衡,需要移动的coins个数的函数helper()。
因为代码比较简单,已经有注释,我就不讲代码了。
c++代码如下:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
int distributeCoins(TreeNode* root) {
int res = 0;
helper(root, res);
return res;
}
// 统计把自身,左右子树都平衡,需要移动的coins个数
void helper(TreeNode* root, int& res) {
if (!root) return;
// 左、右子树缺多少
int left = need(root->left);
int right = need(root->right);
//左,右子树和自身都平衡需要的移动数
res += abs(left) + abs(right);
helper(root->left, res);
helper(root->right, res);
}
// 为了使该子树均匀,需要的coins数
// 节点数 - coins
int need(TreeNode* root) {
if (!root) return 0;
if (count_.count(root))
return count_[root];
int res = need(root->left) + 1 - root->val + need(root->right);
count_[root] = res;
return res;
}
private:
unordered_map<TreeNode*, int> count_;
};
日期
2019 年 1 月 20 日 —— 这次周赛有点简单
【LeetCode】979. Distribute Coins in Binary Tree 解题报告(C++)的更多相关文章
- LeetCode 979. Distribute Coins in Binary Tree
原题链接在这里:https://leetcode.com/problems/distribute-coins-in-binary-tree/ 题目: Given the root of a binar ...
- LC 979. Distribute Coins in Binary Tree
Given the root of a binary tree with N nodes, each node in the tree has node.val coins, and there ar ...
- 【leetcode】979. Distribute Coins in Binary Tree
题目如下: Given the root of a binary tree with N nodes, each node in the tree has node.val coins, and th ...
- 【LeetCode】993. Cousins in Binary Tree 解题报告(C++ & python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS BFS 日期 题目地址:https://le ...
- 【LeetCode】543. Diameter of Binary Tree 解题报告 (C++&Java&Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcode ...
- LeetCode 606 Construct String from Binary Tree 解题报告
题目要求 You need to construct a string consists of parenthesis and integers from a binary tree with the ...
- LeetCode 104 Maximum Depth of Binary Tree 解题报告
题目要求 Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the ...
- 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)
[LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...
- 【LeetCode】297. Serialize and Deserialize Binary Tree 解题报告(Python)
[LeetCode]297. Serialize and Deserialize Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode ...
随机推荐
- Go 类型强制转换
Go 类型强制转换 强制类型的语法格式:var a T = (T)(b),使用括号将类型和要转换的变量或表达式的值括起来 强制转换需要满足如下任一条件:(x是非常量类型的变量,T是要转换的类型) 1. ...
- header 301,显示302
header 301,显示302 一定要注意Location 后面的":"前后都不能有空格 header('HTTP/1.1 301 Moved Permanently'); he ...
- linux 软链接与查看历史指令
ln 说明 软连接也叫符号链接,类似于windows里的快捷方式,主要存放了路径. 基本语法 ln -s[原文件或目录][软连接名] 删除软链接 [root@hadoop102 ~]# rm -rf ...
- A Child's History of England.46
As, one hundred years before, the servile [卑躬屈膝的~serve] followers of the Court had abandoned the Con ...
- absent, absolute, absorb
absent Absenteeism is a habitual [习惯性的] pattern of absence from a duty or obligation [职责] without go ...
- 零基础学习java------day3-运算符 以及eclipse的使用
今日内容: 1. 算数运算符 2. 赋值运算符 3. 关系运算符 4. 逻辑运算符 5. 位运算符 6.三目运算符 一 运算符 运算:对常量和变量进行操作的过程称为运算 运算符:对常量和变量进行操作的 ...
- 安全相关,xss
XSS XSS,即 Cross Site Script,中译是跨站脚本攻击:其原本缩写是 CSS,但为了和层叠样式表(Cascading Style Sheet)有所区分,因而在安全领域叫做 XSS. ...
- 转 Android 多线程:手把手教你使用AsyncTask
转自:https://www.jianshu.com/p/ee1342fcf5e7 前言 多线程的应用在Android开发中是非常常见的,常用方法主要有: 继承Thread类 实现Runnable接口 ...
- fatal: unable to access 'https://github.com/xxxxx/xxxx.git/': Failed to connect to github.com port 443: Timed out
今天使用git push的时候提示"fatal: unable to access 'https://github.com/xxxxx/xxxx.git/': Failed to conne ...
- 【力扣】剑指 Offer 25. 合并两个排序的链表
输入两个递增排序的链表,合并这两个链表并使新链表中的节点仍然是递增排序的. 示例1: 输入:1->2->4, 1->3->4输出:1->1->2->3-> ...