There are N children standing in a line. Each child is assigned a rating value.
You are giving candies to these children subjected to the following requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?
题意:给排成一排的小孩发糖,小孩身高有高有矮。对于任何一对相邻的小孩,两者相对较高的那个
必须得到比矮个更多的糖。此外必须保证每个人至少得到一块糖。
求解所需要准备的糖果总数。
Example 1:
Input: [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.
Example 2:
Input: [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
The third child gets 1 candy because it satisfies the above two conditions.
思路:对于任何一个小孩,他得到的糖要比左右比他矮的小孩的糖更多。这个问题其实与2D蓄水池问题类似,都是和左右比较。所以应该想到从左到右、从右到左各遍历一遍的方法。此外因为本题仅仅是和相邻元素对比,所以单调栈用处不大。
发糖的难点其实是当两相邻小孩等高时的情况,这时两人分配的糖果是存在所有可能性的。
先从左到右遍历,根据rating的大小尽可能少的发糖,即
从左到右的发糖只需要满足两点:
每个小孩至少一块糖(所有小孩初始化1块糖);
左边小孩较矮的话,右边小孩的糖数比他多一个。
任何更少的糖果都无法满足这两点。
再从右到左进行修正,这时候只要满足一点:
右边小孩较矮的话,左边小孩的糖数比他多一个。
任何更少的糖果也都无法满足这一点。
两次遍历的结合就是题设条件,而且是最低满足。
int candy(vector<int>& ratings) {
int len = ratings.size();
vector<int> candy(len, 1);
//left-->right
for (int i = 1; i<len; i++) {
if (ratings[i]>ratings[i - 1])
candy[i] = candy[i - 1] + 1;
}
//right-->left and sum
int sum = candy[len - 1];
for (int i = len - 2; i >= 0; i--) {
if (ratings[i]>ratings[i + 1] && candy[i] <= candy[i + 1])
candy[i] = candy[i + 1] + 1;
sum += candy[i];
}
return sum;
}