作者: 负雪明烛
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. 1<= N <= 100
  2. 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++)的更多相关文章

  1. LeetCode 979. Distribute Coins in Binary Tree

    原题链接在这里:https://leetcode.com/problems/distribute-coins-in-binary-tree/ 题目: Given the root of a binar ...

  2. 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 ...

  3. 【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 ...

  4. 【LeetCode】993. Cousins in Binary Tree 解题报告(C++ & python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 DFS BFS 日期 题目地址:https://le ...

  5. 【LeetCode】543. Diameter of Binary Tree 解题报告 (C++&Java&Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcode ...

  6. LeetCode 606 Construct String from Binary Tree 解题报告

    题目要求 You need to construct a string consists of parenthesis and integers from a binary tree with the ...

  7. 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 ...

  8. 【LeetCode】863. All Nodes Distance K in Binary Tree 解题报告(Python)

    [LeetCode]863. All Nodes Distance K in Binary Tree 解题报告(Python) 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http ...

  9. 【LeetCode】297. Serialize and Deserialize Binary Tree 解题报告(Python)

    [LeetCode]297. Serialize and Deserialize Binary Tree 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode ...

随机推荐

  1. python-django-模板标签

    注意:这个控制语句和python的差不多,但是记住必须有endfor 和endif 结尾 模板文件的django格式的注释是不会出现再网页渲染的源代码当中的 使用列子: <!DOCTYPE ht ...

  2. aboard, abolish

    aboard board做动词有上车/船/飞机的意思,boarding就是正在上.board做名词有板的意思,车厢地板的板. a是个词根,有三种意思:1. 以某种状态或方式,如: ablaze, af ...

  3. day17 常用模块的应用

    day17 常用模块的应用 老师博客园地址:https://www.cnblogs.com/linhaifeng/articles/6384466.html#_label11 一.time与datet ...

  4. Scala和Java的List集合互相转换

    import java.util import scala.collection.mutable /** * 集合互相转换 */ object ScalaToJava { def main(args: ...

  5. 【swift】用Xib实现自定义警告框(Alert)(安卓叫法:Dialog对话框)

    在写这篇博客前,先感谢两篇博客 [如何自定义的思路]:https://www.cnblogs.com/apprendre-10-28/p/10507794.html [如何绑定Xib并且使用]:htt ...

  6. OS开发之Objective-C与JavaScript的交互

    UIWebView是iOS最常用的SDK之一,它有一个stringByEvaluatingJavaScriptFromString方法可以将javascript嵌入页面中,通过这个方法我们可以在iOS ...

  7. my39_InnoDB锁机制之Gap Lock、Next-Key Lock、Record Lock解析

    MySQL InnoDB支持三种行锁定方式: 行锁(Record Lock):锁直接加在索引记录上面,锁住的是key. 间隙锁(Gap Lock): 锁定索引记录间隙,确保索引记录的间隙不变.间隙锁是 ...

  8. 一文读懂RESTful架构

    转载自https://zhuanlan.zhihu.com/p/381554129 RESTful架构究竟是什么 别着急,想要了解RESTful,我们先来了解一位大佬Roy Thomas Fieldi ...

  9. 使用fastDFS上传和下载图片文件

    package com.xuecheng.test.fastdfs;import org.csource.common.MyException;import org.csource.fastdfs.* ...

  10. java中子类继承父类什么?

    1.继承public和protected修饰的属性和方法,不管子类和父类是否在同一个包: 2.继承默认权限修饰符修饰的属性和方法,前提是子类和父类在同一个包.