leetcode :Candy
2015-12-08 16:12
351 查看
There are N children standing in a line. Each child is assigned a rating value.
You are giving candies to these children subjected to the following requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?
思路:等级高的要比相邻的等级低的多一些糖,如果等级一样如[1,2,3, 3, 4, 那[1,2,3,1,2] 给一块糖就可以了。
从左往右遍历,相邻的递增等级,就递增糖果。如果不是递增就跳过-----------只处理从波谷到波峰的糖果
那余下的从波峰到波谷的糖果呢?从右往左,波谷到波峰 不就是 从左往右没有被处理的波峰到波谷
请回想一下:我们为什么需要辅助空间?当孩子的rate是一个非递减曲线的时候,我们是不需要辅助空间的,比如5个孩子的rate分别是1,2,5,7,10。那么糖果数自然是1,2,3,4,5。又如5个孩子的rate分别是1,2,5,5,10,那么糖果数自然是1,2,3,1,2。
因此如果rate是非递减数列,我们可以精确计算出当前孩子应该给多少糖果,把这个糖果数加入总数即可。
当孩子的rate出现递减的情况该如何是好?不用辅助空间能处理吗?
假设5个孩子的rate是 1,5,4,3,2。我们这样计算:遍历时,第一个孩子依然糖果为1,第二个孩子糖果为2,第三个孩子糖果给几个?我们遍历到后面就会知道第二个孩子给的糖果太少了,应该给4个。有没有办法在遍历到后面时,能计算出一个修正值,使得加上这个修正值,正好依然可以使总糖果数是正确的?
其实这个修正值不难计算,因为可以发现递减数列的长度决定了第二个孩子该给几个糖果。仔细观察:遍历到第四个孩子时我们知道了第二个孩子不该给2,应该给3,因此Total 要 +=1;遍历到第五个孩子我们知道了第二个孩子不该给3得给4,因此Total 要 += 1。我们设一个变量beforeDenc表示进入递减序列之前的那个孩子给的糖果值,再设置length用来表达当前递减序列的长度。这两个变量就可以决定Total是不是要修正:当遍历第三个孩子的时候 beforeDenc =
2,以后每遍历一个孩子,因为length已经超过了beforeDenc,每次Total都要额外+1,来修正第二个孩子的糖果数。
对于后面三个孩子,我们可以这样计算:遍历到第三个孩子,因为这是递减数列的第二个数字,我们Total +=
1(length=1;应该是加3颗糖);第四个孩子是递减数列的第三个数字,Total
+= 2(length=2;应该是加2颗糖);第五个孩子是递减数列的第四个数字,Total
+= 3(length=3;应该加1颗糖)。
可以发现最后三个孩子的糖果总数依然是正确的,虽然Total 每次增加的糖果数量length正好和当前孩子得到的糖果数是反序关系。
这种边遍历边修正的方法可以保证一次遍历,不需要O(n)空间下计算出Total的正确值。
参考:/article/6171320.html
You are giving candies to these children subjected to the following requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?
思路:等级高的要比相邻的等级低的多一些糖,如果等级一样如[1,2,3, 3, 4, 那[1,2,3,1,2] 给一块糖就可以了。
从左往右遍历,相邻的递增等级,就递增糖果。如果不是递增就跳过-----------只处理从波谷到波峰的糖果
那余下的从波峰到波谷的糖果呢?从右往左,波谷到波峰 不就是 从左往右没有被处理的波峰到波谷
class Solution { public: int candy(vector<int>& ratings) { int total=0; vector<int> flg(ratings.size(),1);//只有1个糖果 for(int i=1; i<ratings.size(); i++) { //两个连续的rate相等其中一个可能可以只有一个糖果,所以没有等于 if(ratings[i]>ratings[i-1]) // 从每个波谷到波峰,跳过从波峰到波谷的阶段 flg[i]=flg[i-1]+1; } //从后往前从波谷到波峰(如果从前往后看就是前面跳过的从波峰到波谷的阶段) for(int i=ratings.size()-2; i>=0; i--) { if(ratings[i]>ratings[i+1]) flg[i]=max(flg[i+1]+1,flg[i]);//在从前往后时波峰被赋值了,这次从后往前波峰还要赋值,所以取最大值 total+=flg[i]; } return ratings.size() == 0 ? 0 : ( total + flg[ ratings.size()-1 ] ) ; } };
-----------------------------------------------------------------------
Solution (2) 转自:/article/6171320.html
此方法以及代码部分参考了Shangrila 的方法。
请回想一下:我们为什么需要辅助空间?当孩子的rate是一个非递减曲线的时候,我们是不需要辅助空间的,比如5个孩子的rate分别是1,2,5,7,10。那么糖果数自然是1,2,3,4,5。又如5个孩子的rate分别是1,2,5,5,10,那么糖果数自然是1,2,3,1,2。因此如果rate是非递减数列,我们可以精确计算出当前孩子应该给多少糖果,把这个糖果数加入总数即可。
当孩子的rate出现递减的情况该如何是好?不用辅助空间能处理吗?
假设5个孩子的rate是 1,5,4,3,2。我们这样计算:遍历时,第一个孩子依然糖果为1,第二个孩子糖果为2,第三个孩子糖果给几个?我们遍历到后面就会知道第二个孩子给的糖果太少了,应该给4个。有没有办法在遍历到后面时,能计算出一个修正值,使得加上这个修正值,正好依然可以使总糖果数是正确的?
其实这个修正值不难计算,因为可以发现递减数列的长度决定了第二个孩子该给几个糖果。仔细观察:遍历到第四个孩子时我们知道了第二个孩子不该给2,应该给3,因此Total 要 +=1;遍历到第五个孩子我们知道了第二个孩子不该给3得给4,因此Total 要 += 1。我们设一个变量beforeDenc表示进入递减序列之前的那个孩子给的糖果值,再设置length用来表达当前递减序列的长度。这两个变量就可以决定Total是不是要修正:当遍历第三个孩子的时候 beforeDenc =
2,以后每遍历一个孩子,因为length已经超过了beforeDenc,每次Total都要额外+1,来修正第二个孩子的糖果数。
对于后面三个孩子,我们可以这样计算:遍历到第三个孩子,因为这是递减数列的第二个数字,我们Total +=
1(length=1;应该是加3颗糖);第四个孩子是递减数列的第三个数字,Total
+= 2(length=2;应该是加2颗糖);第五个孩子是递减数列的第四个数字,Total
+= 3(length=3;应该加1颗糖)。
可以发现最后三个孩子的糖果总数依然是正确的,虽然Total 每次增加的糖果数量length正好和当前孩子得到的糖果数是反序关系。
这种边遍历边修正的方法可以保证一次遍历,不需要O(n)空间下计算出Total的正确值。
class Solution { public: int candy(vector<int>& ratings) { int total=1; int curNum=1; int length=0; int beforeDenc=1; for(int i=1;i<ratings.size();i++) { if(ratings[i]>ratings[i-1]) { curNum++;//其实是当前的糖果数 total+=curNum; beforeDenc=curNum;//也许是波峰--递减时的第一个,也是递增时的最后一个。。。所以先记录下来,以备下次循环用到!!!! length=0;//递减长度 } else if(ratings[i] < ratings[i-1]) { length++; if(beforeDenc<=length) //有等于 total++;//矫正波峰beforeDenc少了的值, total+=length;//加的是倒序糖果数-length curNum=1;//以备下次循环 递增时用,!!!!!! } else // 等级一样 { curNum=1; total+=curNum; beforeDenc=curNum;//也许是波峰--递减时的第一个,也是递增时的最后一个。。。所以先记录下来,以备下次循环用到!!!! length=0;//递减长度 } } return total; } };
参考:/article/6171320.html
相关文章推荐
- NGUI UILabel 富文本格式说明
- android调用JS失败时可能的原因
- 计算机图形学相关学术期刊会议(转载)
- Requeset使用XML文件格式的报文
- js验证金额格式
- Android中AsyncTask的简单用法
- 学习调用WCF服务的各种方法
- Ubuntu下添加开机启动脚本
- 欢迎使用CSDN-markdown编辑器
- Finding Nemo
- jQuery全屏滚动插件fullPage.js
- Redis实战经验及使用场景
- RelativeLayout 中android:layout_toRightOf无效原因
- Spinner ArrayAdapter
- 【实战Java高并发程序设计 4】数组也能无锁:AtomicIntegerArray
- android orm 框架 ActiveAndroid 使用
- IOS Framework 制作教程 for xcode7 (二)
- 5)二叉树[2]二叉树中序线索化
- 二分查找算法
- 比如C#里面调用AutoCAD ActiveX API实现后台打印DWG文件为PDF文件