if (i < len - 1 && ratings[i] > ratings[i + 1]) right[i] = right[i + 1] + 1;
else right[i] = 1;
最后一次遍历汇总左右规则的结果,满足条件的糖果数为左右数组中的较大值
//sum:存储返回的总糖果数
sum += Math.max(left[i], right[i]);
总代码如下:
public static int candy(int[] ratings) {
int len = ratings.length;
int[] left = new int[len];
for (int i = 0; i < len; i++) {
if (i > 0 && ratings[i] > ratings[i - 1]) left[i] = left[i - 1] + 1;
else left[i] = 1;
}
int[] right = new int[len];
for (int i = len - 1; i >= 0; i--) {
if (i < len - 1 && ratings[i] > ratings[i + 1]) right[i] = right[i + 1] + 1;
else right[i] = 1;
}
int sum = 0;
for (int i = 0; i < len; i++) {
sum += Math.max(left[i], right[i]);
}
return sum;
}
优化
上述方法中经过了三次遍历,并且用到了两个中间数组。
可以对后两次遍历和第二个数组进行优化:
在遍历执行右规则时,可以只需要一个变量记录当前位置的值,同时更新计算总糖果数
代码如下:
public static int candy(int[] ratings) {
int len = ratings.length;
int[] left = new int[len];
for (int i = 0; i < len; i++) {
if (i > 0 && ratings[i] > ratings[i - 1]) left[i] = left[i - 1] + 1;
else left[i] = 1;
}
int right = 0, sum = 0;
for (int i = len - 1; i >= 0; i--) {
if (i < len - 1 && ratings[i] > ratings[i + 1]) right++;
else right = 1;
sum += Math.max(left[i], right);
}
return sum;
}
升序降序(常数空间)
把 ratings 数组看作是由一个个升序序列和降序序列组成的,用 asc 和 des 分别记录最近遍历到的一个升序序列的长度和降序序列的长度,now 记录当前孩子获得的糖果数
public static int candy(int[] ratings) {
int len = ratings.length;
int sum = 1;
//asc:升序序列长度,des:降序序列长度;now:当前孩子获得的糖果数
int asc = 1, des = 0, now = 1;
for (int i = 1; i < len; i++) {
if (ratings[i] >= ratings[i - 1]) {
des = 0;
now = ratings[i] == ratings[i - 1] ? 1 : now + 1;
//糖果数量 == 该升序序列的元素数量
asc = now;
sum += now;
} else {
now = 1;
des++;
if (des == asc) des++;
sum += des;
}
}
return sum;
}