LeetCode135. 分发糖果

题目

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

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

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

限制条件:

n = = r a t i n g s . l e n g t h n == ratings.length n==ratings.length
1 < = n < = 2 ∗ 104 1 <= n <= 2 * 104 1<=n<=2104
0 < = r a t i n g s [ i ] < = 2 ∗ 104 0 <= ratings[i] <= 2 * 104 0<=ratings[i]<=2104

示例

示例 1:

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

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

思路

题意

该题目的意思是:判断每个孩子是否比其相邻孩子的得分高,若得分更高,则分配更多的糖果,且保证相邻孩子中,得分高的孩子比得分低的孩子的糖果数更多。这个分配思路使得得分高,但周围孩子得分同样高的孩子分配的糖果数少,例如对于ratings为[1,3,3,3,1]的输入,最后分配的最少糖果数为[1,2,1,2,1],索引为2的孩子只分配了一个糖果,因为其相邻孩子的得分和他相同,与周围孩子没有区分度。

实现思路

由于题目中的相邻孩子表示其前一个和后一个孩子,所以需要遍历两次,判断当前孩子和其前一个孩子/后一个孩子的得分和糖果数;每次遍历判断当前孩子的得分是否高于其相邻孩子,若高于其相邻孩子,且当前孩子分发的糖果小于等于其相邻孩子分发的糖果,则令当前孩子分发的糖果数为其相邻孩子分发的糖果数加1(需要满足最小糖果数),否则说明糖果数分配的合理,继续遍历。

代码

按照上述思路,C++ 代码实现如下:

class Solution {
public:
    int candy(vector<int>& ratings) {
        int n = ratings.size(), sum=0;
        // 每人分发的糖果数量,每人至少一颗糖果
        vector<int> candies(n, 1); 
        for (int i = 1; i < n; i++){
        	/* 判断第i个孩子是否比第i-1个孩子的评分高,
     		 若第i个孩子评分更高,且第i个孩子的糖果数少于第i-1个孩子, 
        	 则令其糖果数大于前一个孩子的糖果数,为了保证获得最小糖果数,
        	 这里直接对前一个孩子的糖果数加1来表示第i个孩子的糖果数
        	*/ 
            if (ratings[i] > ratings[i - 1] && candies[i] <= candies[i - 1]){
                candies[i] = candies[i - 1] + 1;
            }
        }
        sum += candies[n - 1];
        /* 反向遍历原理同上,此时需要判断第i个孩子和第i + 1个孩子
           两次循环结束后把分配的糖果数相加即为最少分发的糖果数
           这里为了减少循环的次数,直接在第二个循环下计算最小分发的糖果数量
        */
        for (int i = n - 2; i >= 0; i--){
            if (ratings[i] > ratings[i + 1] && candies[i] <= candies[i + 1]){
                candies[i] = candies[i + 1] + 1;
            }
            sum += candies[i];
        }
        return sum;
    }
};

复杂度分析

两次循环遍历的时间复杂度为O(n)(常数项2忽略),由于保存了每个孩子分发的糖果数量,空间复杂度为O(n)。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值