原题链接
一. 题目描述
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 <= n <= 2 * 104
0 <= ratings[i] <= 2 * 104
二. 解题思路
本题题意也是比较清楚,给每一个孩子分配糖果,至少一颗,每个孩子的左侧或者右侧的孩子的评分如果比相邻的孩子高则分到的糖果的数量也多。问满足条件分到的最少的糖果总数;
我们首先定义一个关于每一个孩子分到糖果数量的vector 数组,然后我们就得考虑怎样分配糖果才能使得每一个孩子的左右侧都满足,如果你想同时满足两侧显然是不可能的,所以我i们分为两步执行,先满足右侧,再倒着执行一次,满足左侧的孩子。
如下图所示,我们先从左到右遍历一遍,如果当前的大于左侧的,就在左侧的位置上加1作为当前分配的糖果数量,否则直接分配1。
再从右往左比较右孩子的大小,如果当前位置的大于右侧孩子就将当前位置的糖果和右侧孩子的糖果加1 取一个最大值即可。
最后只需要遍历一遍将结果累加输出即可。
话不多说!!!上代码!!
三. 代码
class Solution {
public:
int candy(vector<int>& ratings) {
int n = ratings.size();
vector<int> candy(n);
candy[0] = 1;
for(int i = 1; i < n; i++){ // 从左到右开始遍历
if(ratings[i] > ratings[i - 1]){
candy[i] = candy[i - 1] + 1;
}else{
candy[i] = 1;
}
}
// candy[n - 1] = 1;
for(int i = n - 2; i >= 0; i--){ // 从右往左开始遍历
if(ratings[i] > ratings[i + 1]){
candy[i] = max(candy[i], candy[i + 1] + 1);
}
}
int res = 0;
for(int i = 0; i < n; i++){
res += candy[i];
}
return res;
}
};
四. 总结
本题理解起来很简单,但是真正做起来并不简单,需要将思路梳理好,只要多做就能理解,加油!!!
时间复杂度:O(n);
空间复杂度:O(n)。