问题:979. 在二叉树中分配硬币

给定一个有 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. 1<= N <= 100
  2. 0 <= node.val <= N

链接:https://leetcode-cn.com/contest/weekly-contest-120/problems/distribute-coins-in-binary-tree/

分析:

0.每个节点硬币存在如下几种流向:给父节点、给左子节点、给右子节点;

1.将左右节点看做一个整体,向上和向下流向是对称的,只需要统计一个方向的即可,而且左右节点看做一个整体,分发后在分别内部递归进行后续分发;

2.如果某个节点为空,则流动次数为0;

3.如果某个节点不为空,左节点节点数Node1,硬币数Coins1,右节点数Node2,硬币数Coins2,由于节点数和硬币数一致,所以差值的绝对值即需要的流动次数,即父节点给左节点的X个硬币加上父节点给右节点的Y个硬币是这一层的流动次数

4.分别计算左右节点的移动次数,累加即为结果。

AC Code:

/**
* 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 ret = ;
if (root == NULL)
{
return ;
}
else
{
int tmpleftnodes = ;
int tmpleftconins = ;
int tmprightnodes = ;
int tmprightcoins = ;
int tmpselfnode = ;
int tmpselfcoins = ;
GetInfo(root, tmpleftnodes, tmpleftconins, tmprightnodes, tmprightcoins, tmpselfnode, tmpselfcoins); int tmpdeltaleft = tmpleftconins - tmpleftnodes;
int tmpdeltaright = tmprightcoins - tmprightnodes;
//int tmpselfdelta = tmpselfcoins - tmpselfnode;
int tmpselfdelta = ;
ret = ret + abs(tmpselfdelta - tmpdeltaleft) + abs(tmpselfdelta - tmpdeltaright);
ret = ret + distributeCoins(root->left) + distributeCoins(root->right);
} return ret; }
//获得该节点左右节点数以及所拥有的硬币数
void GetInfo(TreeNode* root, int& leftnodes, int& leftconins, int& rightnodes, int& rightcoins,int& selfnode,int& selfcoins)
{
if (root == NULL)
{
leftnodes = ;
leftconins = ;
rightnodes = ;
rightcoins = ;
selfnode = ;
selfcoins = ;
return;
}
else if (root->left == NULL && root->right == NULL)
{
leftnodes = ;
leftconins = ;
rightnodes = ;
rightcoins = ;
selfnode = ;
selfcoins = root->val;
return;
}
else //if (root->left != NULL && root->right != NULL)
{
int tmpleftnodes = ;
int tmpleftconins = ;
int tmprightnodes = ;
int tmprightcoins = ;
int tmpselfnode = ;
int tmpselfcoins = ;
GetInfo(root->left, tmpleftnodes, tmpleftconins, tmprightnodes, tmprightcoins, tmpselfnode, tmpselfcoins);
leftnodes = tmpleftnodes + tmprightnodes + tmpselfnode;
leftconins = tmpleftconins + tmprightcoins + tmpselfcoins; tmpleftnodes = ;
tmpleftconins = ;
tmprightnodes = ;
tmprightcoins = ;
tmpselfnode = ;
tmpselfcoins = ;
GetInfo(root->right, tmpleftnodes, tmpleftconins, tmprightnodes, tmprightcoins, tmpselfnode, tmpselfcoins);
rightnodes = tmpleftnodes + tmprightnodes + tmpselfnode;
rightcoins = tmpleftconins + tmprightcoins + tmpselfcoins;
selfnode = ;
selfcoins = root->val;
}
} };

其他:

1.由于左右均衡是通过父节点实现的,所以其实不需要看父节点的硬币数量

2.第一code:

typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)
#define FOR(x,to) for(x=0;x<(to);x++)
#define FORR(x,arr) for(auto& x:arr)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define ALL(a) (a.begin()),(a.end())
#define ZERO(a) memset(a,0,sizeof(a))
#define MINUS(a) memset(a,0xff,sizeof(a))
//------------------------------------------------------- class Solution {
public:
int ret;
pair<int,int> count(TreeNode* root) {
pair<int,int> A={,root->val};
if(root->left) {
auto a=count(root->left);
A.first+=a.first;
A.second+=a.second;
}
if(root->right) {
auto a=count(root->right);
A.first+=a.first;
A.second+=a.second;
}
ret+=abs(A.first-A.second);
return A;
} int distributeCoins(TreeNode* root) {
ret=;
count(root);
return ret;
}
};

pair记录节点个数和所拥有的硬币数,差值都是需要流动的

另一个code:

/**
* 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 sgn(int x) {
if (x == 0)
return 0;
return x < 0 ? -1 : 1;
}
int maxTurbulenceSize(vector<int>& A) {
int n = A.size();
int l = 0;
int ans = 1;
for (int r = 1; r < n; ++r) {
if (l + 1 < r and sgn(a[r] - a[r - 1]) == sgn(a[r - 1] - a[r - 2])) {
l = r - 1;
}
if (a[r] == a[r - 1]) {
l = r;
}
ans = max(ans, r - l + 1);
} return ans;
}
}; */ class Solution {
public:
int sz(TreeNode* root) {
if (root == nullptr)
return ;
return + sz(root->left) + sz(root->right);
} int coins(TreeNode* root) {
if (root == nullptr) {
return ;
} return root->val + coins(root->left) + coins(root->right);
} int distributeCoins(TreeNode* root) {
// number of coins over edge = diff between coins and nodes for each subtree
if (root == nullptr) {
return ;
}
return abs(coins(root) - sz(root)) + distributeCoins(root->left) + distributeCoins(root->right);
}
};

LeetCode979. 在二叉树中分配硬币的更多相关文章

  1. [Swift]LeetCode979. 在二叉树中分配硬币 | 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 ...

  2. Leetcode979 : Distribute Coins in Binary Tree 二叉树均匀分配硬币问题

    问题 给定一个二叉树的root节点,二叉树中每个节点有node.val个coins,一种有N coins. 现在要求移动节点中的coins 使得二叉树最终每个节点的coins value都为1.每次移 ...

  3. C语言实现二叉树中统计叶子结点的个数&度为1&度为2的结点个数

    算法思想 统计二叉树中叶子结点的个数和度为1.度为2的结点个数,因此可以参照二叉树三种遍历算法(先序.中序.后序)中的任何一种去完成,只需将访问操作具体变为判断是否为叶子结点和度为1.度为2的结点及统 ...

  4. python3实现在二叉树中找出和为某一值的所有路径

    在二叉树中找出和为某一值的所有路径请写一个程序创建一棵二叉树,并按照一定规则,输出二叉树根节点到叶子节点的路径.规则如下:1.从最顶端的根结点,到最下面的叶子节点,计算路径通过的所有节点的和,如果与设 ...

  5. 在Quartus II中分配管脚的两种常用方法

    在Quartus II中分配管脚的两种常用方法 示范程序 seg7_test.v 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 /* * ...

  6. IT公司100题-11-求二叉树中节点的最大距离

    问题描述: 写程序,求一棵二叉树中相距最远的两个节点之间的距离. 10/     \6      14/   \   /   \4    8 12    16 分析: 二叉树中最远的两个节点,要么是根 ...

  7. 动态链接库中分配内存引起的问题-- windows已在XX.exe中触发一个断点

    动态链接库中分配内存引起的 本文主要是探讨关于在动态链接库分配的内存在主程序中释放所产生的问题,该问题是我在刚做的PJP工程中所遇到的,由于刚碰到之时感动比较诡异(这也是学识不够所致),所以将它写下来 ...

  8. 二叉树中序遍历 (C语言实现)

    在计算机科学中,树是一种重要的非线性数据结构,直观地看,它是数据元素(在树中称为结点)按分支关系组织起来的结构.二叉树是每个节点最多有两个子树的有序树.通常子树被称作“左子树”(left subtre ...

  9. 94 Binary Tree Inorder Traversal(二叉树中序遍历Medium)

    题目意思:二叉树中序遍历,结果存在vector<int>中 解题思路:迭代 迭代实现: /** * Definition for a binary tree node. * struct ...

随机推荐

  1. 谷歌添加百度翻译提示Google已将百度翻译标记为恶意程序并阻止安装,怎么办

    进入谷歌浏览器的设置, 显示高级设置——隐私设置下七个选项中的第四个选项(启用针对网上诱骗和恶意软件的防护功能)把勾去掉,然后将百度翻译的CRX拖动到chrome的安装插件页面, 修改chrome的限 ...

  2. Unity C# ref与out

    ref和out 都是按地址传递的,使用后都将改变原来的数值.ref 方法参数关键字使方法引用传递到方法的同一个变量.当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中.若要使用 r ...

  3. iOS-swift-函数和闭包

    一.函数 关键字:func 参数列表用 , 分割 使用 -> 分割参数和返回值 func greet(person: String, day: String) -> String { re ...

  4. 利用DOS命令做伪装成图片的压缩包,看上去是图片其实是个压缩包用2条命令即搞定

    在很多地方我们看到一张图片,然后把这张图片下载到本地,改后缀名为xx.rar,即变成了压缩包. 比如下面这个图片:(把以下图片保存到本地,后缀名xx.png 改为 xx.rar,解压试试) 怎么样,是 ...

  5. C#让窗体在启动时直接隐藏

    最完美的解决办法,不闪烁.思路为:首先将窗体透明度设置为0,这样窗体在启动时就不显示了,然后再调用Hide将窗体隐藏再将其透明度设置为1即可. 其实就设置2个地方就行了. 1:设置窗体透明度为0 2: ...

  6. 内表转WORD

    组合HTML字符串的方法来导出WORD文件 DATA: BEGIN OF wa_html, zhtml(), END OF wa_html, gt_html LIKE TABLE OF wa_html ...

  7. Brackets - 前端神器

    做了几年的 .Net 项目开发,后来公司转 Java 语言开发,Java 做了还没一年,公司准备前后端分离开发,而我被分到前端! Brackets是一款基于web(html+css+js)开发的web ...

  8. Programming for thread in Java

    Programming for thread in Java Override Annotation package java.lang; import java.lang.annotation.El ...

  9. Shader笔记

    1,渲染队列值小的先渲染,值大的后渲染 2,zTest,zWrite zTest:LEqua zWrite:On 则:zWrite中,深度值小于深度值缓冲区的值会被通过 参考:http://www.c ...

  10. 如何找到Android app启动activity和页面元素信息

    在实施app自动化的时候,我们需要知道app 的启动activity和页面元素信息,以此启动app和定位页面元素,那么如何在没有源码的情况下找打他们呢?当然是有好的工具啦,有Android sdk自带 ...