其他分享
首页 > 其他分享> > 135.分发糖果

135.分发糖果

作者:互联网

目录

135.分发糖果

题目

老师想给孩子们分发糖果,有 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解

如果开始比较两侧,那么在比较过程中,一个更改,前面的所有都会更改,但是没有记录前面元素的大小关系,整个过程非常的混乱。

选择单侧比较,先从左到右(比较左侧),再从右到左(比较右侧)。那么单侧需要比较两次,就需要一个candy数组记录每个小孩得到糖果的个数,第二次循环才好在第一次的基础上选择。

题目的条件等价于下面两条规则: AB

左规则处理 递增区间 是正确的, 右规则处理 递减区间 是正确的

如果i的评分大于i-1的评分,所以i的糖果数比i-1的大1。

那么如果i的评分小于i-1的评分呢?是candy[i]=candy[i-1]-1吗?这里先不处理这种情况,因为每个小孩至少有一个糖果,如果减了之后等于0了,就不符合条件了。
其实不处理也可以,如下图所示,元素1小于元素2,在第二次遍历时,元素2大于元素1,那么2的糖果比1的糖果多1也等价于第一次遍历时元素1的糖果比元素2的糖果少1的效果。

image

第一次循环先让所有学生满足左规则:如果当前学生评分比左边的多,要比左边学生的糖多1个。
循环完之后最后一个小孩的糖果数一定是确定的。
因为最后一个小孩只需要和左边的比,第一次循环之后就比较完成了。
假设:那万一前一个小孩的糖果数变大了,最后一个还比他大呢?那不是最后一个没有确定吗?
第一次循环,倒数第二已经和左边的比较了,那么下一次他只会和右边的比较,最后一个比他大,它就不变,所以不会出现上面的假设。

for(int i=1;i<len;i++){
   if(ratings[i]>ratings[i-1]) candyNum[i] = candyNum[i-1] + 1;
}

第二次循环的时候,比较i号小孩与 i + 1 号孩子,也就是比较右侧。
利用最后一个小孩的糖果数是确定的,从后往前比较右边的小孩。candyNum[i]只有取最大的才能保证比左边大也比右边大。

image

 for(int i=len-2;i>=0;i--){
   if(ratings[i]>ratings[i+1]) candyNum[i] = Math.max(candyNum[i],candyNum[i+1] + 1);
   sum+=candyNum[i];
}

代码

class Solution {
    public int candy(int[] ratings) {
        int len = ratings.length;   
        if(len == 1) return 1;
        int [] candyNum = new int [len];
        Arrays.fill(candyNum,1);
        for(int i=1;i<len;i++){
            if(ratings[i]>ratings[i-1]) candyNum[i] = candyNum[i-1] + 1;
        }
        int sum = candyNum[len-1];
         for(int i=len-2;i>=0;i--){
            if(ratings[i]>ratings[i+1]) candyNum[i] = Math.max(candyNum[i],candyNum[i+1] + 1);
            sum+=candyNum[i];
        }
        return sum;
    }
}

标签:分发,ratings,int,candyNum,len,135,糖果
来源: https://www.cnblogs.com/rananie/p/15060785.html