算法—分配糖果

一、题目

有N个孩子站成一排,每个孩子有一个分值。现在你需要为这些孩子分配糖果,但需要满足下面的需求:

  • 每个孩子至少分一个。
  • 拥有较高分值的孩子得到的糖果要比与他相邻的孩子得到的数量多

那么最少需要给这些孩子分配多少糖果?

二、分析

1、如果孩子当前的分值大于前一个孩子,当前孩子分得糖果数量应该是 前一个孩子分得糖果数加1
下图中curr代表当前孩子,图中上半部分对应每个孩子的分值,下半部分对应每个孩子分配的糖果数.
后文中此类图形同理。
在这里插入图片描述
2、如果当前孩子的分值等于前一个孩子的分值,则当前孩子所分得糖果数量应该是1。(注意题干是:分配最少糖果)
在这里插入图片描述
3、如果连续下降的,如果当前孩子的分值小于前一个孩子的分值,我们还不能得出当前位置的糖果数是多少(不知道有多少连续下降数),继续看下面
在这里插入图片描述
孩子所具有的分值连续下降时,那么我们使用countDown来存放连续下降数。下图中,在curr位置处countDown = 2。(3-2,2-1)
在这里插入图片描述
如果在下降序列中,当前值等于前一个人的值或大于前一个人的值,那么不在构成下降序列,那么我们将通过数列求和公式来计算这段连续下降序列的长度。下图为等差数列求和公式。
在这里插入图片描述
当计算下降区间长度时,需要考虑pre变量。下图中pre为2,因此接下来的两次糖果分配数量,无法按依次递减的方式分配,因为这样,因此第2次分配的数量将会是0,而每个孩子最少要分配一个。
在这里插入图片描述
在这种情况下,countDown >= prew,这样我们需要修改pre位置处为孩子分配的糖果数,pre = countdown – pre + 1。修正后可以保证每个孩子至少分配一个。

三、代码实现

public static int candy(int[] ratings) {
       /**
         * pre:前面元素能够得到的糖数
         * countDown:连续下降数
         * total:最少分配的糖果数
         */
        int pre = 1, countDown = 0, total = 1;
        for (int i = 1; i < ratings.length; i++) {
            if (ratings[i] >= ratings[i - 1]) { //当前元素大于等于前一元素
                if (countDown > 0) {
                    total += countDown * (countDown + 1) / 2;
                    if (countDown >= pre) {
                        total += countDown - pre + 1;
                    }
                    pre = 1;
                    countDown = 0;
                }
                //如果当前元素等于前一元素,则当前元素为1,否则,当前元素+1
                pre = ratings[i] == ratings[i - 1] ? 1 : pre + 1;
                total += pre;
            } else {  //当前元素小于前一元素
                countDown++;
            }
        }
        if (countDown > 0) {
            total += countDown * (countDown + 1) / 2;
            if (countDown >= pre) {
                total += countDown - pre + 1;
            }
        }
        return total;
    }

四、鸣谢

文章1:http://www.allenlipeng47.com/blog/index.php/2016/07/21/candy/
文章2:https://blog.csdn.net/revivedsun/article/details/52897147

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是贪心算法的分糖果问题的报告。 问题描述: 有 $n$ 个小朋友和 $m$ 颗糖果,每个小朋友有一个贪心指数 $g_i$,表示他对糖果的喜爱程度。我们需要按照以下要求分配糖果: 1. 每个小朋友至少分到一个糖果。 2. 如果一个小朋友的贪心指数比他旁边的小朋友高,那么他应该得到比旁边的小朋友更多的糖果。 目标是最小化所分发的糖果数量。 解决方案: 首先,我们可以为每个小朋友分配一个糖果。这样,每个小朋友都至少有一个糖果了。 接着,我们需要考虑如何分配剩下的糖果。我们从左到右遍历每个小朋友,如果当前小朋友的贪心指数比前一个小朋友高,那么我们让他的糖果数量比前一个小朋友多一颗。否则,我们只给他一颗糖果。 同样的,我们也要从右到左遍历一遍小朋友,如果当前小朋友的贪心指数比后一个小朋友高,那么我们让他的糖果数量比后一个小朋友多一颗。这样,我们就可以满足所有小朋友的要求了。 最后,我们需要统计一下分配出去的糖果数量。这个数量就是所有小朋友糖果数量之和。 时间复杂度: 对所有小朋友进行两次遍历,所以时间复杂度为 $O(n)$。 代码实现: 下面是 Python 语言的代码实现。 ```python def min_candies(n, g): # 每个小朋友至少分到一个糖果 candies = [1] * n # 左遍历 for i in range(1, n): if g[i] > g[i-1]: candies[i] = candies[i-1] + 1 # 右遍历 for i in range(n-2, -1, -1): if g[i] > g[i+1]: candies[i] = max(candies[i], candies[i+1] + 1) # 统计糖果数量 return sum(candies) ``` 测试样例: 我们可以使用以下样例进行测试。 ```python n = 5 g = [1, 2, 3, 2, 1] print(min_candies(n, g)) # 输出 7 ``` 这个样例中,我们有 $5$ 个小朋友,他们的贪心指数分别为 $[1,2,3,2,1]$。根据贪心算法,我们将分配 $[1,2,3,1,1]$ 颗糖果,总共需要 $7$ 颗糖果

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值