文章目录
- 题目
- 解
- ① 穷举法,用时3ms,超过26.93%
- ②穷举法改进,用时2ms,超过97.78%
题目
n
个孩子站成一排。给你一个整数数组 ratings
表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
- 每个孩子至少分配到
1
个糖果。 - 相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
示例 1:
输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。
示例 2:
输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。
解
① 穷举法,用时3ms,超过26.93%
数组正序,当前元素和前后的元素比较,如果大则要保证比相邻的同学糖果多1个,数组逆序检查,如果当前同学的评分比相邻同学高,则保证比相邻同学糖果多1个。
注:下面的代码为了简化,设置了每个同学初始获得的糖果为0,计算完成之后再给每个同学发一个糖果,保证每人至少1个,所以candy数组并不是实际发放的糖果数目,还要在计算之后每个元素+1
问题:为什么正序之后,还要逆序检查?
答:假设没有逆序检查,用例ratings输入为[1,2,87,87,87,2,1]时,candy=[0,1,2,0,1,1,0]。当for循环运行到最后一个‘87’时,candy=[0,1,2,0,0,0,0],下一个评分为‘2’的同学,此时分配的糖果数目为0,所以最后一个‘87’分的同学满足比相邻同学的糖果多1个,分配糖果数目为1,即candy=[0,1,2,0,1,0,0]。然后运行至分数为‘2’的同学那里,按照和相邻同学对比的原则,最终可得1个糖果,因为他的糖果数目发生改变,所以之前分配给‘87’分同学的数目就少了一个,不满足原题目条件,故最后需要逆序检查。
问题:既然要检查,为什么不改成如果当前元素的糖果发生变化,就对上一个进行检查呢?
答:这个思路尝试后发现,如果当前同学的糖果增加了,上一个同学的糖果可能也会变化,上一个同学的糖果如果变化,那么上上个同学也应该检查。如此循环反复,就会变成每一次发生变化之后,就得检查前面所有的同学是否要改变,比逆序检查一次所耗费的时间更多。举个例子,ratings=[1,16,10,8,7,3,2],如果按照只检查上一次的话,最终的candy=[0,1,2,2,2,1,0],不符合题目要求。
class Solution {public int candy(int[] ratings) {int[] candy=new int[ratings.length];//数组初始所有元素为0int num=0;//数组正序,检查每个同学和相邻同学评分for(int i=0;i<ratings.length;i++){if(i!=ratings.length-1 && ratings[i]>ratings[i+1]){// 如果该同学比下一个同学分数高,则他的糖果要比下一个同学多1个candy[i]=candy[i+1]+1;}if(i!=0 && ratings[i]>ratings[i-1]){// 如果该同学比上一个同学分数高,则他的糖果要比下一个同学多1个candy[i]=candy[i-1]+1;}}//数组逆序,检查分配是否有误for(int i=ratings.length-1;i>=0;i--){if(i!=0 && ratings[i]>ratings[i-1] && candy[i]<=candy[i-1]){// 如果该同学比上一个同学分数高,并且糖果少于上一个同学,则他要比上个同学多一个candy[i]=candy[i-1]+1;}if(i!=ratings.length-1 && ratings[i]>ratings[i+1] && candy[i]<=candy[i+1]){// 如果该同学比下一个同学分数高,并且糖果少于下一个同学,则他要比下个同学多一个candy[i]=candy[i+1]+1;}}for(int j=0;j<ratings.length;j++){// 将数组的所有元素相加num+=candy[j];}return num+ratings.length;//每个同学至少一个糖果,所以返回值加上length}
}
②穷举法改进,用时2ms,超过97.78%
和①的区别在于,①每次循环都是和前后两个元素进行比较,②正循环的时候只和左边元素比较,倒序的时候只和右边元素比较
删掉了两个if的部分,对代码进行了简化
class Solution {public int candy(int[] ratings) {int[] candy=new int[ratings.length];int num=0;for(int i=0;i<ratings.length;i++){if(i!=0 && ratings[i]>ratings[i-1]){candy[i]=candy[i-1]+1;}}for(int i=ratings.length-1;i>=0;i--){if(i!=ratings.length-1 && ratings[i]>ratings[i+1] && candy[i]<=candy[i+1]){candy[i]=candy[i+1]+1;}}for(int j=0;j<ratings.length;j++){num+=candy[j];}return num+ratings.length;}
}