LeetCode题解:Candy

There are N children standing in a line. Each child is assigned a rating value.

You are giving candies to these children subjected to the following requirements:

  • Each child must have at least one candy.
  • Children with a higher rating get more candies than their neighbors.

What is the minimum candies you must give?

题意:有N个小孩子站成一行,每一个人有一个权重,然后给他们发糖果。发糖果需要满足以下条件:

  • 每一个小孩必须有一个糖果
  • 权重更高的小孩糖果应该比他们旁边的小孩要多

求最少需要多少糖果

思路:首先有一种发糖果的情况是可以确定分配方法的:到第i个小孩,权重条形图呈非递减状。

即:

  1. 如果i+1个小孩的权值大于i个小孩,那么i+1个小孩的糖果数量为i个小孩的数量+1
  2. 如果i+1个小孩的权值等于i个小孩,i+1个小孩的糖果数量为1(暂时假设i+1为最后一个小孩)

也就是说,唯一需要讨论的情况就是:i+1个小孩的权值小于i个小孩(同理i个小孩的权值与i+j个小孩相等([i+1,i+j],j>1),i+j+1个小孩权值小于i个小孩)

在这种情况下,影响i个小孩能得到的糖果数量是i+1个小孩的糖果数量,因为i个小孩的权值比i+1个小孩大,使得i+1个小孩的糖果数量要比i个小孩多。此外,由于[0,i-1]个小孩我们假设是非降序序列,因此i个小孩的糖果数量又应该比i-1个小孩要多。

也就是说,当区间[i,j]中的小孩权值呈凸形图(即有中间是顶峰,两边递减),顶峰对应的小孩能得到的糖果数量受左右小孩糖果数量的影响。这样就可以设计式子计算了。

代码:

public class Solution {
    public int candy(int[] ratings) {
        if(ratings == null || ratings.length == 0){
            return 0;
        }

        int res = 1;
        int prev = 1;
        int desLength = 0;

        for(int i = 1; i < ratings.length; i++){
            if(ratings[i] >= ratings[i - 1]){
                if(desLength > 0){
                    res += desLength * (desLength + 1) / 2;
                    if(desLength >= prev){
                        res += desLength - prev + 1;
                    }

                    prev = 1;
                    desLength = 0;
                }

                prev = ratings[i] == ratings[i - 1] ? 1 : prev + 1;
                res += prev;
            } else {
                desLength++;
            }
        }

        if(desLength > 0){
            res += desLength * (desLength + 1) / 2;
            if(desLength >= prev){
                res += desLength - prev + 1;
            }
        }

        return res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值