LeetCode 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 * 10^4
0 <= ratings[i] <= 2 * 10^4
我们可以先给每个孩子都分一颗糖果,然后就可以在循环中给孩子分0颗糖果了。分组循环,先严格递增再严格递减的连续子数组为一组,就像一个山峰,但这个山峰可以是一半的,即只有严格递增部分或只有严格递减部分。除峰顶外,假设上升阶段有n个,那么可以依次给0、1、2...n-1个糖果,假设下降阶段有m个,那么可以依次给m-1、m-2...0个糖果,然后给峰顶max(n,m)个糖果。这样以山峰为单位,山脚位置都给0颗糖(因为我们已经给每个孩子都分了一颗糖),可以避免山脚位置的重复计算。然后分组循环,一个山峰是一组,计算每组的糖数即可:
class Solution {
public:int candy(vector<int>& ratings) {int n = ratings.size();int ans = 0;int i = 0;while (i < n) {int start = i;++i;// 上升阶段while (i < n && ratings[i] > ratings[i - 1]) {++i;}int top = i - 1;// 下降阶段while (i < n && ratings[i] < ratings[i - 1]) {++i;}int up = 0;// 上升阶段的评分数if (start > 0 && ratings[start] > ratings[start - 1]) {up = top - start + 1;} else {up = top - start;}// 下降阶段的评分数int down = i - top - 1;ans += (up * (up - 1)) / 2 + (down * (down - 1)) / 2 + max(up, down);}return ans + ratings.size();}
};
如果ratings的大小为n,那么该算法时间复杂度为O(n),空间复杂度为O(1)。