[LeetCode] Candy (分糖果),时间复杂度O(n),空间复杂度为O(1),且只需遍历一次的实现
[LeetCode] Candy (分糖果),时间复杂度O(n),空间复杂度为O(1),且只需遍历一次的实现
原题:
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?
Solution (1)
这题本身可以用贪心法来做,我们用candy[n]表示每个孩子的糖果数,遍历过程中,如果孩子i+1的rate大于孩子i 的rate,那么当前最好的选择自然是:给孩子i+1的糖果数=给孩子i的糖果数+1
如果孩子i+1的rate小于等于孩子i 的rate咋整?这个时候就不大好办了,因为我们不知道当前最好的选择是给孩子i+1多少糖果。
解决方法是:暂时不处理这种情况。等数组遍历完了,我们再一次从尾到头遍历数组,这回逆过来贪心,就可以处理之前略过的孩子。
最后累加candy[n]即得到最小糖果数。
这种解法是需要O(n)的辅助空间给candy[]的。
有没有更好的办法?
Solution (2) 此方法以及代码部分参考了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;第四个孩子是递减数列的第三个数字,Total += 2;第五个孩子是递减数列的第四个数字,Total += 3。
可以发现最后三个孩子的糖果总数依然是正确的,虽然Total 每次增加的糖果数量正好和当前孩子得到的糖果数是反序关系。
这种边遍历边修正的方法可以保证一次遍历,不需要O(n)空间下计算出Total的正确值。
代码:

int candy(vector<int> &ratings) {
int Total = 0; /// Total candies
int length = 0; /// Continuous descending length of rate
int nPreCanCnt = 1; /// Previous child's candy count
int beforeDenc = nPreCanCnt;
if(ratings.begin() != ratings.end())
{
Total++; //Counting the first child's candy (1).
for(vector<int>::iterator i = ratings.begin()+1; i!= ratings.end(); i++)
{
if(*i < *(i-1))
{
length++;
if(beforeDenc <= length)
{
Total++;
}
Total += length;
nPreCanCnt = 1; //This step is important, it ensures that once we leave the decending sequence, candy number start from 1
}
else
{
int curCanCnt = 0;
if(*i > *(i-1))
{
curCanCnt = (nPreCanCnt + 1);
}
else
{
curCanCnt = 1;
}
Total += curCanCnt;
nPreCanCnt = curCanCnt;
length = 0; //reset length of decending sequence
beforeDenc = curCanCnt;
}
}
}
return Total;
}

[LeetCode] Candy (分糖果),时间复杂度O(n),空间复杂度为O(1),且只需遍历一次的实现的更多相关文章
- [LeetCode] Candy 分糖果问题
There are N children standing in a line. Each child is assigned a rating value. You are giving candi ...
- [LeetCode] Candy Crush 糖果消消乐
This question is about implementing a basic elimination algorithm for Candy Crush. Given a 2D intege ...
- Java实现 LeetCode 575 分糖果(看看是你的长度小还是我的种类少)
575. 分糖果 给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果.你需要把这些糖果平均分给一个弟弟和一个妹妹.返回妹妹可以获得的最大糖果的种类数. 示例 1: 输入 ...
- [LintCode] Candy 分糖果问题
There are N children standing in a line. Each child is assigned a rating value. You are giving candi ...
- Leetcode 135.分糖果
分发糖果 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分. 你需要按照以下要求,帮助老师给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果. 相邻的孩 ...
- 清北学堂模拟赛d2t6 分糖果(candy)
题目描述总共有n颗糖果,有3个小朋友分别叫做L,Y,K.每个小朋友想拿到至少k颗糖果,但这三个小朋友有一个共同的特点:对3反感.也就是说,如果某个小朋友拿到3颗,13颗,31颗,333颗这样数量的糖果 ...
- [Leetcode] candy 糖果
There are N children standing in a line. Each child is assigned a rating value. You are giving candi ...
- [LeetCode] 723. Candy Crush 糖果消消乐
This question is about implementing a basic elimination algorithm for Candy Crush. Given a 2D intege ...
- LeetCode 1103. Distribute Candies to People (分糖果 II)
题目标签:Math 题目让我们分发糖果,分的糖果从1 开始依次增加,直到分完. for loop可以计数糖果的数量,直到糖果发完.但是还是要遍历array 给people 发糖,这里要用到 index ...
随机推荐
- 四则运算 SPEC 20160911
本文档随时可能修改,并且没有另行通知. 请确保每一次在开始修改你的代码前,读标题中的日期,如果晚于你上次阅读, 请重读一次. 教师节你去探望初中数学老师,她感叹你当年真是个优秀学生啊,从来不报怨作 业 ...
- 【Alpha】功能规格说明书
更新说明:从用户需求分析中剥离有关用户场景分析部分,加入功能规格说明书. Github地址:https://github.com/buaase/Phylab-Web/blob/master/docs/ ...
- DHCP全局配置文件解析
作用 参数 ddns-update-style 类型 定义DNS服务动态更新的类型,类型包括:none(不支持动态更新), interim (互动更新模式)与ad-hoc(特殊更新模式) allow ...
- vm15安装esxi6.0
vmware 15安装esxi6.0时发现出现没有硬盘选择,导致无法安装 在vm12上安装正常 经过测试 1.需要在虚拟机硬件兼容性上选择12.x 2.版本也要选6.0,不要选6.X 其次,esxi要 ...
- QEMU简单知识 以及磁盘格式转换的简单命令
From 百度百科 QEMU,是由 Fabrice Bellard开发的通用.开源机器模拟与虚拟化软件,Fabrice Bellard是另一个著名的C编译器的作者.QEMU可以在不同的机器上运行独自开 ...
- JIRA部署破解和confluence整合
JIRA是一个项目跟踪管理工具,帮助团队创建计划任务.构建并发布优秀的产品.全球成千上万的团队选择JIRA,用JIRA来捕获.组织管理缺陷.分配任务,跟踪团队的活动.不论在桌面PC还是移动终端设备上, ...
- 一本通1641【例 1】矩阵 A×B
1641: [例 1]矩阵 A×B sol:矩阵乘法模板.三个for循环 #include <bits/stdc++.h> using namespace std; typedef lon ...
- Eclipse RCP学习资料
1.拥抱Eclipse RCP http://www.blogjava.net/youxia/category/17374.html 2.RCP工程下面自动生成了如下文件:Application.ja ...
- wamp安装失败原因大全
wamp 是 Windos.Apache.Mysql.PHP集成安装环境 为了安装hdwiki 所以需要这个环境 1.下载wampserver_x86_3.0.6 64位 环境包,安装路径禁止有空格 ...
- 洛谷U19464 山村游历(Wander)(LCT)
洛谷题目传送门 LCT维护子树信息常见套路详见我的总结 闲话 题目摘自WC模拟试题(by Philipsweng),原题目名Wander,"山村游历"是自己搞出来的中文名. 数据自 ...