leetcode-135 candy(分发糖果)
题目:
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。
你需要按照以下要求,帮助老师给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。 相邻的孩子中,评分高的孩子必须获得更多的糖果。 那么这样下来,老师至少需要准备多少颗糖果呢?
示例 1:
输入: [1,0,2] 输出: 5 解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。 示例 2:
输入: [1,2,2] 输出: 4 解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。 第三个孩子只得到 1 颗糖果,这已满足上述两个条件。
思路:
首先读完题目可以知道有两点要满足的是:
1.每个孩子至少有一颗糖果,就是说默认至少糖果数是等于孩子个数的
2.相邻的孩子评分高的糖果也要多,所以评分有不等于的关系时,分数高的糖果数多,同时也可以得出评分相同时,糖果数没有影响,大于小于等于都有可能
一开始我的想法是相邻的两个孩子评分比较,只要有不等于关系糖果就加一,最后在加上默认每个孩子的一个糖果(也就是孩子个数).这样会产生两个问题
一个是1,2,1这样对称的评分会多加出来一颗糖果,第二个是分数有递增和递减(这里的递增递减指的是分数的大小是增加的还是减少的)混合在一起的时候吧,无法确定递减的糖果数是多少,比如1,2,6,4,2,1.
前三个会推出来糖果数1,2,3但是第四个孩子的糖果数其实会依赖于他后面孩子的分数.
所以我最后是采用的遍历两次的方式,从左至右,在从右至左遍历一次.从左至右只算递增的,右边的大于左边的,就右边的糖果数等于左边的糖果数加一,如果不是递增关系就默认为1.
看上面1,2,6,4,2,1的例子遍历一遍就是1,2,3,1,1,1.前三个满足递增关系所以是1,2,3,后三个不满足所以默认是1.
再从右往左遍历的时候递减的时候(就是左边的评分小于右边的评分)不需要加上,第一遍遍历的时候右边糖果数已经是大于左边的糖果数.
从右往左遍历1,2,6,4,2,1糖果数变为1,2,3,3,2,1,因为3,3相等,所以左边这个3会变为4,最后是1,2,4,3,2,1.
最后把所有糖果数相加起来是13.
代码
public static int candy(int[] ratings) {
int[] sumArr = new int[ratings.length];
int sum = 0;
sumArr[0] = 1;
for (int i = 1; i < ratings.length; i++) {
// 从左到右 右大于左 并且糖果数就加一
if (ratings[i] > ratings[i - 1]) {
sumArr[i] = sumArr[i - 1] + 1;
} else {
sumArr[i] = 1;
}
}
for (int i = ratings.length - 1; i > 0; i--) {
// 从右到做 左大于右 并且糖果数左边小于右边 就加一
if (ratings[i - 1] > ratings[i] && sumArr[i - 1] <= sumArr[i]) {
sumArr[i - 1] = sumArr[i] + 1;
}
}
for (int item : sumArr) {
sum += item;
}
return sum;
}