135. 分发糖果

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

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

每个孩子至少分配到 1 个糖果。
相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例 1:

输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

示例 2:

输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。

提示:

n == ratings.length
1 <= n <= 2 * 104
0 <= ratings[i] <= 2 * 104

贪心算法。
方法一:孩子的rate和candy需要满足的关系是,相邻孩子中rate高的那一个会分的更多的candy。如果同时考虑3,4,5等等个孩子,会混乱。故选择两次遍历的方法。
第一次遍历:从左往右,如果右孩子的rate>左孩子,右孩子的糖果=左孩子的糖果+1;
第二次遍历:从右往左,如果左孩子的rate>右孩子,左孩子的糖果=右孩子的糖果+1;
需要一个n维数组存储每个孩子的糖果数,空间复杂度o(n),时间复杂度o(n);

class Solution {
    public int candy(int[] ratings) {
        int candies = ratings.length;
        int [] candy = new int [ratings.length];
        for(int i=1; i<ratings.length; i++){
            if(ratings[i]>ratings[i-1]){
                
                candy[i] =candy[i-1] + 1;
            }
        }

        for(int i=ratings.length-1; i>0; i--){
            if(ratings[i-1]>ratings[i]){
                if(candy[i]>=candy[i-1]){
                    candy[i-1]=candy[i]+1;
                }
            }
        }

        for(int i=0; i<candy.length; i++){
            candies += candy[i];
        }
        return candies;

    }
}

方法2:如果时间复杂度为o(1)呢?不用数组记录每个孩子的糖果,直接算经过每个孩子时,总的糖果数要增加的值。
一个很巧妙的方法。具体分析如下:
情况1
rate递增:1,2,3,4,5;
candy数: 1,2,3,4,5;
情况2
rate递减:5,4,3,2,1;
candy数: 5,4,3,2,1;
可以看作:1,2,3,4,5;
对于孩子0,先给1糖,
孩子2和1对比,比之小,则其实孩子2:1,孩子1:2;
孩子3和2对比,比之小,则其实孩子1:3,孩子2:2,孩子3:1;
因为孩子至少要有1糖的,用一种倒序的方法看,则每次递减后 加上的数 是当前递减的次数。

情况3
不增不减趋势持平:由样例2知,给1

情况4
举例:
1,2,3,4,5,6,7,8
3,4,5,4,3,2,1,0
按照上方的推断,每个孩子得到的糖果应为: 1,2,3,5,4,3,2,1
可以发现,3孩子和4孩子的糖果数满足条件。这是因为递增的次数为3,而当分到6孩子时,递减的次数已经等于递增的次数了,这个时候,应该给递增的最后一个孩子+一个糖;如果递减的次数>递增的怎么办?继续加糖。(倒序着看就明了了)

设置inc(增加的次数),dec(减少的次数),以及candy数,pre(当前的糖果数)
部分代码如下

**情况1+3**
            if(ratings[i]>=ratings[i-1]){
                dec = 0;
                pre = ratings[i]==ratings[i-1] ? 1:pre+1;
                candy += pre;
                inc = pre;

**情况2+4**  
          else{
                dec ++;
                if(dec==inc){
                    dec++;  // 倒序,相当于为inc中最后   dec超过inc的数目  的孩子加了糖。
                }
                candy += dec;
                pre = 1;
            }

完整代码

class Solution {
    public int candy(int[] ratings) {
        int inc = 1;
        int dec = 0;
        int candy = 1;
        int pre = 1;
        for(int i=1; i<ratings.length; i++){
            if(ratings[i]>=ratings[i-1]){
                dec = 0;
                pre = ratings[i]==ratings[i-1] ? 1:pre+1;
                candy += pre;
                inc = pre;
            }else{
                dec ++;
                if(dec==inc){
                    dec++;
                }
                candy += dec;
                pre = 1;
            }
        }
        return candy;
    }
}
posted @   啤酒加点醋  阅读(74)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
点击右上角即可分享
微信分享提示