135. 分发糖果
n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
相邻两个孩子中,评分更高的那个会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。
示例 1:
输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。
示例 2:
输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。
这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,如果两边一起考虑一定会顾此失彼。
先确定右边评分大于左边的情况(也就是从前向后遍历)
此时局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果
局部最优可以推出全局最优。
如果ratings[i] > ratings[i - 1] 那么[i]的糖 一定要比[i - 1]的糖多一个,所以贪心:candyVec[i] = candyVec[i - 1] + 1
总结
这在leetcode上是一道困难的题目,其难点就在于贪心的策略,如果在考虑局部的时候想两边兼顾,就会顾此失彼。
那么本题我采用了两次贪心的策略:
一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
这样从局部最优推出了全局最优,即:相邻的孩子中,评分高的孩子获得更多的糖果。
这道题要求给 n 个孩子分发糖果。用长度为 n 的数组 candies 表示每个孩子得到的糖果数,则应满足以下两个要求。
对于任意 0≤i<n 都有 candies[i]≥1。
对于任意 j−i=1,当 ratings[i]<ratings[j] 时应满足 candies[i]<candies[j],当 ratings[i]>ratings[j] 时应满足 candies[i]>candies[j]。
根据贪心策略,为了使分发的糖果数目最少,应在满足两个要求的情况下最小化分发给每个孩子的糖果数目。
首先将 candies 中的所有元素初始化为 1,表示每个孩子至少得到 1 颗糖果,然后正向和反向遍历数组 ratings 各一次,更新 candies 中的元素。
正向遍历时,对于 i>0,执行如下操作。
如果 ratings[i]>ratings[i−1],则必须满足 candies[i]>candies[i−1],为了使 candies[i] 最小,将 candies[i] 的值更新为 candies[i−1]+1。
如果 ratings[i]≤ratings[i−1],则不需要满足 candies[i]>candies[i−1],因此 candies[i] 的值保持不变。
正向遍历结束之后,candies 中的元素满足条件:对于 i>0,如果 ratings[i]>ratings[i−1] 则 candies[i]>candies[i−1]。此时 candies 中的元素为满足要求的最小元素,将 candies 中的任意元素减少都无法满足要求,因此第 i 个孩子得到的最少糖果数一定大于等于此时的 candies[i]。
反向遍历时,candies 中的元素不可能减少,对于 i<n−1,执行如下操作。
如果 ratings[i]>ratings[i+1],则必须满足 candies[i]>candies[i+1],因此 candies[i] 必须大于等于 candies[i+1]+1,为了使 candies[i] 最小,如果 candies[i]<candies[i+1]+1 则将 candies[i] 的值更新为 candies[i+1]+1。
如果 ratings[i]≤ratings[i+1],则不需要满足 candies[i]>candies[i+1],因此 candies[i] 的值保持不变。
反向遍历结束之后,candies 中的元素满足条件:对于 i<n−1,如果 ratings[i]>ratings[i+1] 则 candies[i]>candies[i+1]。此时 candies 中的元素为满足要求的最小元素,将 candies 中的任意元素减少都无法满足要求。
两次遍历结束之后,计算 candies 中的元素之和,即为需要给孩子分发的最少糖果数目。
`
class Solution {
public int candy(int[] ratings) {
int n = ratings.length;
int[] candies = new int[n];
Arrays.fill(candies, 1);
for (int i = 1; i < n; i++) {
if (ratings[i] > ratings[i - 1]) {
candies[i] = candies[i - 1] + 1;
}
}
for (int i = n - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1]) {
candies[i] = Math.max(candies[i], candies[i + 1] + 1);
}
}
int total = 0;
for (int num : candies) {
total += num;
}
return total;
}
}
`
浙公网安备 33010602011771号