题目描述
个孩子站成一排。给你一个整数数组表示每个孩子的评分。 你需要按照以下要求,给这些孩子分发糖果:
- 每个孩子至少分配到个糖果。
- 相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目。
用例
输入:
输出:
解释: 你可以分别给第一个、第二个、第三个孩子分发 、、 颗糖果。
输入:
输出:
解释:你可以分别给第一个、第二个、第三个孩子分发 、、 颗糖果。
第三个孩子只得到 颗糖果,这满足题面中的两个条件。
题目分析
刷高畅大佬的leetcode101遇到的题,它是最值问题,一般可能考贪心,但仍没想到如何处理(既要考虑左侧,又要考虑右侧....),特此记录一番,以便后续再刷。 该问题要根据相邻孩子的评分,分配最少糖果数目。
如果仅仅考虑孩子与后一个孩子的评分,问分配最少糖果数目。那么我们只需从左往右遍历一次,如果后一位同学比前一位同学评分高,那么后一位同学糖果数是前一位同学糖果数目加,否则糖果数为(以保证最少糖果数)。
但是,这只能保证同学与后一同学的糖果满足条件,忽略了同学与前一同学糖果上的约束。那么如果我们从右往左遍历一次,便可以保证同学与前一同学糖果上的约束了(需要注意,从右往左遍历的时候,不要破坏先满足的约束)。
这题目是一道贪心问题,难点是需要考虑两侧同学以满足糖果上的约束(相邻同学评分高,糖果多)并求最少糖果数。局部贪心是让单侧同学先满足糖果上的约束并求最少糖果数。那为什么局部最优能保证全局最优呢?直观上,如果存在更少的糖果数,那么必然有一位同学多分了糖果,但是,这种情况显然不存在的。
代码
class Solution {
public:
int candy(vector<int>& ratings) {
vector<int> num(ratings.size(), 1);
int count= 0;
for(int i= 1; i< ratings.size(); i++){
if(ratings[i]> ratings[i- 1]){num[i]= num[i- 1]+ 1;}
}
for(int j= ratings.size()- 2; j>= 0; j--){
if(ratings[j]> ratings[j+ 1]){num[j]= (num[j+ 1]+ 1> num[j]? num[j+ 1]+ 1: num[j]);}
count+= num[j];
}
count+= num[ratings.size()- 1];
return count;
}
};
其中,时间复杂度.