[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 ...
随机推荐
- java入门--4111:判断游戏胜者-Who Is the Winner
基础的题目 学习了StringBuilder, 通过delete来清空它 学了Map的简单用法 import java.util.*; public class Main { public stati ...
- Python 安装 imread报错
看到一篇博客才解决 http://blog.csdn.net/u010480899/article/details/52701025
- [转帖][Bash Shell] Shell学习笔记
[Bash Shell] Shell学习笔记 http://www.cnblogs.com/maybe2030/p/5022595.html 阅读目录 编译型语言 解释型语言 5.1 作为可执行程序 ...
- 微信小程序填坑之旅一(接入)
一.小程序简介 小程序是什么? 首先“程序”这两个字我们不陌生.看看你手机上的各个软件,那就是程序.平时的程序是直接跑在我们原生的操作系统上面的.小程序是间接跑在原生系统上的.因为它嵌入在微信中,受微 ...
- C# 妈妈再打我一下生成器
设计背景 网上很火的一个"妈妈再打我一下"的漫画图片,给了网友无限的想象发挥空间,此小程序可以给图片添加配文的形式,快速生成图片 设计思路 GDI+ 绘图技术,在图片基础上添加文字 ...
- Tomcat源码解析-整体流程介绍
一.架构 下面谈谈我对Tomcat架构的理解 总体架构: 1.面向组件架构 2.基于JMX 3.事件侦听 1)面向组件架构 tomcat代码看似很庞大,但从结构上看却很清晰和简单,它主要由一堆组件组成 ...
- Spring点滴九:Spring bean的延迟初始化
Spring bean延迟初始化: 官网API: By default, ApplicationContext implementations eagerly create and configure ...
- Django入门项目实践(下)
5.设置应用程序的样式 安装django-bootstrap3. # untitled/untitled/settings.py # ··· INSTALLED_APPS = [ 'django.co ...
- 【CF522A】Reposts
题目大意:给定一个有向图,求图中最长路. 题解:直接拓扑排序后按照拓扑序枚举即可.处理时应将字符串通过 map 映射成一个点,同时注意字符串大小写转换,C++ string 中没有提供直接大小写转换的 ...
- Java后台面试 常见问题
Java后台面试 常见问题 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米.百度.阿里.京东.新浪.CVTE.乐视家的研发岗offer.我找的是java后台开发,把常见的问题分享 ...