问题

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。

你需要按照以下要求,帮助老师给这些孩子分发糖果:

每个孩子至少分配到 1 个糖果。
相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?

示例 1:
输入: [1,0,2]
输出: 5
解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。

示例 2:
输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这已满足上述两个条件。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/candy
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

思路

转载leetcode官方解答:

首先我们给每个学生 1 个糖果,然后我们从左到右遍历并分配糖果,我们仅更新评分比左邻居高且糖果数小于等于左邻居的学生,将其更新为 candies[i] = candies[i-1] + 1。在更新的过程中,我们不需要比较 candies[i] 和 candies[i - 1] ,因为在更新前一定有 candies[i]≤candies[i−1] 。

从左到右遍历完后,我们同样地从右到左遍历。现在我们需要更新每个学生 i 同时满足左邻居和右邻居的关系。在这次遍历汇总,如果 ratings[i]>ratings[i + 1] ,仅考虑右邻居规则的情况下,我们本应该更新为 candies[i] = candies[i + 1] + 1,但是这次我们仅当 candies[i]≤candies[i+1] 才更新。这是因为我们在从左到右遍历的时候已经修改过 candies 数组,所以 candies[i]不一定小于等于 candies[i + 1]。所以,如果 ratings[i] > ratings[i + 1],我们更新为candies[i]=max(candies[i],candies[i+1]+1]) ,这样 candies[i]同时满足左邻居和右邻居的约束。

再一次,我们把 candiescandies 数组中的所有元素求和,获得所需结果。

class Solution {
    public int candy(int[] ratings) {
        if(ratings == null || ratings.length == 0){
            return 0;
        }
        int[] nums = new int[ratings.length];//记录每一位孩子得到的糖果数
        nums[0] = 1;
        //先正序遍历,如果后一位比前一位高分,就给比前一位多1的糖果,否则给1
        for(int i = 1; i < ratings.length; i++){
            if(ratings[i] > ratings[i-1]){
                nums[i] = nums[i-1] + 1;        
            }else {
                nums[i] = 1;
            }
        }
        //再倒着遍历,如果前一位比后一位高分并且得到的糖果小于或等于后一位,就给前一位孩子比后一位孩子多一个糖果
        for(int i = ratings.length -2 ; i >= 0; i--){
            if(ratings[i] > ratings[i+1] && nums[i] <= nums[i+1]){
                nums[i] = nums[i+1] +1;
            }
        }
        int count = 0;
        for(int i : nums){
            count +=i;
        }
        return count;
    }
}