当前位置:网站首页>Leetcode(135)——分发糖果
Leetcode(135)——分发糖果
2022-06-24 19:03:00 【SmileGuy17】
Leetcode(135)——分发糖果
题目
n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
- 每个孩子至少分配到 1 个糖果。
- 相邻两个孩子评分更高的孩子会获得更多的糖果。
- 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
示例 1:
输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。
示例 2:
输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。
提示:
- n == ratings.length
- 1 1 1 <= n <= 2 ∗ 1 0 4 2 * 10^4 2∗104
- 0 0 0 <= ratings[i] <= 2 ∗ 1 0 4 2 * 10^4 2∗104
题解
方法一:贪心算法
思路
我们可以将「相邻的孩子中,评分高的孩子必须获得更多的糖果」这句话拆分为两个规则,分别处理。
- 左规则:当 ratings [ i − 1 ] < ratings [ i ] \textit{ratings}[i - 1] < \textit{ratings}[i] ratings[i−1]<ratings[i] 时, i i i 号学生的糖果数量将比 i − 1 i - 1 i−1 号孩子的糖果数量多。
- 局部最优:只要右边评分比左边大,右边的孩子就多一个糖果 c a n d y V e c [ i ] = c a n d y V e c [ i − 1 ] + 1 candyVec[i] = candyVec[i - 1] + 1 candyVec[i]=candyVec[i−1]+1;
- 全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果
- 右规则:当 ratings [ i ] > ratings [ i + 1 ] \textit{ratings}[i] > \textit{ratings}[i + 1] ratings[i]>ratings[i+1] 时, i i i 号学生的糖果数量将比 i + 1 i + 1 i+1 号孩子的糖果数量多。
- 局部最优:取 c a n d y V e c [ i + 1 ] + 1 candyVec[i + 1] + 1 candyVec[i+1]+1 和 c a n d y V e c [ i ] candyVec[i] candyVec[i] 最大的糖果数量,保证第 i i i 个小孩的糖果数量即大于左边的也大于右边的;
- 全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。
我们遍历该数组两次,处理出每一个学生分别满足左规则或右规则时,最少需要被分得的糖果数量。每个人最终分得的糖果数量即为这两个数量的最大值。
具体地,以左规则为例:我们从左到右遍历该数组,假设当前遍历到位置 i i i,如果有 ratings [ i − 1 ] < ratings [ i ] \textit{ratings}[i - 1] < \textit{ratings}[i] ratings[i−1]<ratings[i] 那么 i i i 号学生的糖果数量将比 i - 1i−1 号孩子的糖果数量多,我们令 left [ i ] = left [ i − 1 ] + 1 \textit{left}[i] = \textit{left}[i - 1] + 1 left[i]=left[i−1]+1 即可,否则我们令 left [ i ] = 1 \textit{left}[i] = 1 left[i]=1。
在实际代码中,我们先计算出左规则 left \textit{left} left 数组,在计算右规则的时候只需要用单个变量记录当前位置的右规则,同时计算答案即可。

为什么取最大值是正确的思考:
我们取序列中的任意两点,A B
- 如果 A > B ,则按照左规则处理后,B不会比A多;按照右规则处理后,A一定比B多,那么A一定会被更新(变大),但L、R规则仍然成立:B不会比A多,A一定比B多;
- 同理可讨论 A<B;
- 当 A == B,A、B的值无论如何更新,都不影响 L、R规则
综上,取最大值后不影响某一规则的成立。
代码实现
class Solution {
public:
int candy(vector<int>& ratings) {
int kid, size = ratings.size();
vector<int> num(size, 1);
kid = 1;
while(kid < size){
if(ratings[kid-1] < ratings[kid]) num[kid] = num[kid-1] + 1;
kid++;
}
kid = size-1;
while(kid > 0){
if(ratings[kid-1] > ratings[kid]) num[kid-1] = max(num[kid-1], num[kid] + 1);
kid--;
}
return accumulate(num.begin(), num.end(), 0);
}
};
复杂度分析
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是孩子的数量。我们需要遍历两次数组以分别计算满足左规则或右规则的最少糖果数量。
空间复杂度: O ( n ) O(n) O(n),其中 n n n 是孩子的数量。我们需要保存所有的左规则对应的糖果数量。
方法二:常数级空间复杂度
思路
注意到糖果总是尽量少给,且从 1 1 1 开始累计,每次要么比相邻的同学多给一个,要么重新置为 1 1 1。依据此规则,我们可以画出下图:

其中相同颜色的柱状图的高度总恰好为 1 , 2 , 3 … 1,2,3 \dots 1,2,3…。
而高度也不一定一定是升序,也可能是 … 3 , 2 , 1 \dots 3,2,1 …3,2,1 的降序:

注意到在上图中,对于第三个同学,他既可以被认为是属于绿色的升序部分,也可以被认为是属于蓝色的降序部分。因为他同时比两边的同学评分更高。我们对序列稍作修改,下面是新序列——我们注意到右边的降序部分变长了(从3变为了4),使得第三个同学不得不被分配 4 4 4 个糖果。

依据前面总结的规律,我们可以提出本题的解法:我们从左到右枚举每一个同学,记前一个同学分得的糖果数量为 pre \textit{pre} pre:
- 如果当前同学比上一个同学评分高,说明我们就在最近的递增序列中,直接分配给该同学 pre + 1 \textit{pre} + 1 pre+1 个糖果即可。
- 否则我们就在一个递减序列中,我们直接分配给当前同学一个糖果,并把该同学所在的递减序列中所有的同学都再多分配一个糖果,以保证糖果数量还是满足条件。
- 我们无需显式地额外分配糖果,只需要记录当前的递减序列长度,即可知道需要额外分配的糖果数量。
- 同时注意当当前的递减序列长度和上一个递增序列等长时,需要把最近的递增序列的最后一个同学也并进递减序列中。
这样,我们只要记录当前递减序列的长度 dec \textit{dec} dec,最近的递增序列的长度 inc \textit{inc} inc 和前一个同学分得的糖果数量 pre \textit{pre} pre 即可。
代码实现
class Solution {
public:
int candy(vector<int>& ratings) {
int n = ratings.size();
int ret = 1;
int inc = 1, dec = 0, pre = 1;
for (int i = 1; i < n; i++) {
if (ratings[i] >= ratings[i - 1]) {
dec = 0;
pre = ratings[i] == ratings[i - 1] ? 1 : pre + 1;
ret += pre;
inc = pre;
} else {
dec++;
if (dec == inc) {
dec++;
}
ret += dec;
pre = 1;
}
}
return ret;
}
};
复杂度分析
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是孩子的数量。我们需要遍历两次数组以分别计算满足左规则或右规则的最少糖果数量。
空间复杂度: O ( 1 ) O(1) O(1),我们只需要常数的空间保存若干变量。
边栏推荐
- When querying the database with Gorm, reflect: reflect flag. mustBeAssignable using unaddressable value
- The four stages of cloud computing development have finally been clarified
- Two solutions to the problem of 0xv0000225 unable to start the computer
- 华为云ModelArts第四次蝉联中国机器学习公有云服务市场第一!
- The latest simulated question bank and answers of the eight members (Electrical constructors) of Sichuan architecture in 2022
- C语言实现扫雷(简易版)
- 字节、腾讯也下场,这门「月赚3000万」的生意有多香?
- 云计算发展的 4 个阶段,终于有人讲明白了
- 基于SSM的物料管理系统(源码+文档+数据库)
- [go language questions] go from 0 to entry 4: advanced usage of slice, elementary review and introduction to map
猜你喜欢

Image panr

得物多活架构设计之路由服务设计

Bytebase joins Alibaba cloud polardb open source database community
![[video tutorial] functions that need to be turned off in win10 system. How to turn off the privacy option in win10 computer](/img/14/0313857adc178ecee4c866a05e54aa.jpg)
[video tutorial] functions that need to be turned off in win10 system. How to turn off the privacy option in win10 computer

1、 Downloading and installing appium

Apple doesn't need money, but it has no confidence in its content

Two solutions to the problem of 0xv0000225 unable to start the computer

Audio and video 2020 2021 2022 basic operation and parameter setting graphic tutorial

Openstack actual installation and deployment tutorial, openstack installation tutorial

使用gorm查询数据库时reflect: reflect.flag.mustBeAssignable using unaddressable value
随机推荐
unity之模糊背景(带你欣赏女人的朦胧美)
Predicate
IP address to integer
gateway
OpenVINO2022 Dev Tools安装与使用
云计算发展的 4 个阶段,终于有人讲明白了
CVPR 2022缅怀孙剑!同济、阿里获最佳学生论文奖,何恺明入围
建立自己的网站(14)
情绪识别AI竟「心怀鬼胎」,微软决定封杀它!
Methods for comparing float types in the kernel
lol手游之任务进度条精准计算
Openvino2022 dev tools installation and use
Apple, Microsoft and Google will no longer fight each other. They will work together to do a big thing this year
图的基本概念以及相关定义
Introduction: continuously update the self-study version of the learning manual for junior test development engineers
Predicate
Apache+PHP+MySQL环境搭建超详细!!!
Some ideas about chaos Engineering
Comparative analysis of arrayblockingqueue and linkedblockingqueue
C語言實現掃雷(簡易版)