目录
题目描述:
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?
有N个孩子站成一排,每个孩子有一个分值。给这些孩子派发糖果,需要满足如下需求:
- 1、每个孩子至少分到一个糖果
- 2、分值更高的孩子比他相邻的孩子获得更多的糖果
求至少需要分发多少糖果?
要求示例:
输入描述:0,1,0
输出描述:4
输入示例:5,4,1,1
输出示例:7
题目分析:
- 每个孩子至少一个;
- 分值高的比相邻的孩子糖果多;
假如输入:1,2,2,那第一个孩子1个,第二个孩子2个,第三个孩子呢?按题意,分1个就行。也就是至少四个。
思路一:
- 初始将每个孩子的糖果数都设为1;
- 从左向右扫描,保证一个方向上分数更大的糖果更多;
- 从右向左扫描,保证另一个方向上分数更大的糖果更多。
import java.util.Arrays;
public class Solution {
public int candy(int[] ratings) {
if(ratings == null || ratings.length == 0) {
return 0;
}
//初始将每个孩子的糖果数都设为1
int[] count = new int[ratings.length];
Arrays.fill(count, 1);
int sum = 0;
//从左向右扫描,保证一个方向上分数更大的糖果更多
for (int i = 1; i < ratings.length; i++) {
if (ratings[i] > ratings[i - 1]) {
count[i] = count[i-1] + 1;
}
}
//从右向左扫描,保证另一个方向上分数更大的糖果更多
for (int i = ratings.length - 1; i > 0; i--) {
sum += count[i];
//左侧分值高于右侧,左侧糖果数不多于右侧
if (ratings[i] < ratings[i - 1] && count[i] >= count[i-1]) {
//左侧糖果数等于右侧糖果数+1
count[i-1] = count[i]+1;
}
}
sum += count[0];
return sum;
}
}
思路二:
- 从头开始,第一个小朋友给一个糖果,若是升序,则后面小朋友的糖果数依次+1,一直遇到降序。
- 遇到降序怎么处理?因为我们需要给尽可能少的糖果,但需要保证降序的最后一个至少有一个糖果。
- 此时采用贪心策略:先得到降序的位数,用等差求和,公差为1,算出递减阶段需要给的糖果数,递减的最后一个人肯定是给1个。
- 此时还需要注意:递减开始的小朋友的糖果不能比它的前一个小朋友多,如果多了,那需要额外补给他的前一个小朋友糖果,来满足题目第二个条件。
例子: 假如输入序列是 [1,3,5,7,6,5,4,3,2,1], 前四个小朋友糖果数分别为1,2,3,4。从第五个小朋友开始变成递减序列。那个第五个小朋友至少分到:6个。可是第四个小朋友7大于第五个小朋友6,但7只有4个糖果而6有6个,显然不合理,为满足题目第二个条件,所以必须给7小朋友补发糖,要补多少个糖果呢?两个小朋友相差6-4=2个,但是补2个无法满足要求,所以要补2+1=3个,也就是小朋友7拿到7个,小朋友6拿6个,这才符合题目要求。
public class Solution {
public int candy(int[] ratings) {
if (ratings == null || ratings.length == 0) {
return 0;
}
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;
}
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;
}
}