题目描述
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。你需要按照以下要求,帮助老师给这些孩子分发糖果:
- 每个孩子至少分配到 1 个糖果。
- 相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?
输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这已满足上述两个条件。
解题思路
从左遍历到右,在从右遍历到左,最后统计最大值就完事啦。(贪心,我的实现)
-
贪心法(推荐,我的实现。 )
-
规则定义: 设学生A和学生B左右相邻,A在B左边:
- 左规则: 当 时,B的糖比A的糖数量多。
- 右规则: 当 时,A的糖比B的糖数量多。
相邻的学生中,评分高的学生必须获得更多的糖果 等价于 所有学生满足左规则且满足右规则。
-
算法流程:
-
先从左至右遍历学生成绩
ratings
,按照以下规则给糖,并记录在数组left
中:- 先给所有学生
1
颗糖; - 若
,则第
i
名学生糖比第i - 1
名学生多1
个。 - 若
,则第
i
名学生糖数量不变。(交由从右向左遍历时处理)
经过此规则分配后,可以保证所有学生糖数量 满足左规则 。
- 先给所有学生
-
同理,在此规则下从右至左遍历学生成绩并记录在数组
right
中,可以保证所有学生糖数量 满足右规则 -
最终,取以上
2
轮遍历left
和right
对应学生糖果数的 最大值 ,这样则 同时满足左规则和右规则 ,即得到每个同学的最少糖果数量。
-
-
-
更优算法:(只看看思路二就好, )
参考代码
class Solution {
public:
int candy(vector<int>& ratings) {
int length = ratings.size();
vector<int> left(length, 1);
vector<int> right(length, 1);
for(int i = 1; i < length; i++){
if(ratings[i] > ratings[i-1])
left[i] = left[i-1] + 1;
}
for(int i = length-2; i >= 0; i--){
if(ratings[i] > ratings[i+1])
right[i] = right[i+1] + 1;
}
int res = 0;
for(int i = 0; i < length; i++)
res += max(left[i], right[i]);
return res;
}
};