老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。
你需要按照以下要求,帮助老师给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/candy
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
话不多说,咱们来直接看题。
由题,我们可以知道,此题求的是糖果的最小值。先不要着急解题,我们想一下力扣455分饼干问题,https://blog.csdn.net/DadadaHeidi/article/details/121367259?spm=1001.2014.3001.5501。
在分饼干问题中,因为要尽可能多的满足孩子们的胃口,所以我们运用了贪心的策略。而此题,求糖果的最小值,我们也理应想到贪心思想。
那么,既然说到了贪心,贪心的策略是:保证每次操作的结果都是局部最优的,从而使最终结果是全局最优的。
此题的局部最优是两两比较,但是又不足以服众,所以我们需要两次遍历,一次从左到右,一次从右到左。
既然是最小,又不能小于1,那么理想状态就是每个孩子一个糖果为最少。
由于传入的数组长度是未知的,所以我们首先需要判断,是否需要做比较的情况,即只有一个元素。此时,直接给孩子一个糖果,既是局部最优,也是全局最优。
由于系统给我们的还是vector容器,其有一个成员函数为size(),返回容器长度。
ratings是孩子们的评分,所以我们需要再创建一个vector容器,用于存放分给对应孩子的糖果的个数。
上文说过,理想状态下,大家评分都一样,每个人一个糖果是最少的一种情况(如果元素个数恒定),所以,我们初始化新容器每一个元素都为1,长度为size。
局部最优,即两两对比。因为数组随机(老师对孩子的评分不一定是升序或者降序),所以我们需要做两次遍历。一次从左到右,如果右边孩子的评分大于左边孩子,那么右边孩子的糖果数量在左边孩子的基数上加一。然后,再从右到左进行遍历,如果左边孩子的评分大于右边,且左边孩子的糖果数量小于右边,那么左边孩子的糖果数量等于右边孩子糖果数量基数加一;如果,左边评分和糖果数量都高于右边,则不变。
此时有必要提一下,对比的两个孩子的评分相等就不在对比范围之内:
评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。
没有更高就还是1.
所以完整的代码就是:(放的力扣格式)