算法:
这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,如果两边一起考虑一定会顾此失彼。
1.右孩子>左孩子(从左向右遍历)
局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,
全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果
// 从前向后
for (int i = 1; i < ratings.size(); i++) {
if (ratings[i] > ratings[i - 1]) candyVec[i] = candyVec[i - 1] + 1;
}
2.左孩子>右孩子(从右向左遍历)
为什么要从右向左遍历?
假设还是从左向右遍历:
所以左孩子>右孩子时,
因为 rating[5]与rating[4]的比较
要利用上 rating[5]与rating[6]的比较结果,
所以 要从后向前遍历。
局部最优:取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,保证第i个小孩的糖果数量既大于左边的也大于右边的。
全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。
// 从后向前
for (int i = ratings.size() - 2; i >= 0; i--) {
if (ratings[i] > ratings[i + 1] ) {
candyVec[i] = max(candyVec[i], candyVec[i + 1] + 1);
}
}
正确代码:
class Solution {
public int candy(int[] ratings) {
int len = ratings.length;
int[] candyVec = new int[len];
int result = 0;
candyVec[0] = 1;
//右孩子>左孩子,从左向右遍历
for (int i =1; i<len; i++){
if (ratings[i] > ratings[i-1]){
candyVec[i] = candyVec[i-1]+1;
}
//否则,candyVec[i] = 1
else candyVec[i] = 1;
}
//左孩子>右孩子,从右向左遍历
for(int i =len-2;i>=0; i--){
if (ratings[i+1] < ratings[i]){
candyVec[i] = Math.max(candyVec[i],candyVec[i+1]+1);
}
}
//求结果
for(int i = 0; i<candyVec.length; i++){
result += candyVec[i];
}
return result;
}
}
注意:
1.右孩子大于左孩子时,若右边评分比左边大,右边的孩子就多一个糖果;
否则,也要给孩子一个糖果
2.左孩子大于右孩子时,for循环中,i的初始值为len-2
这样可以确保在循环中访问 `ratings[i + 1]
` 时不会越界。
举个例子,ratings = [1, 0, 2],len=3,i初始为1。
若
i的初始值为len-1,则i初始为2,ratings[i + 1]=ratings[3],超出索引范围,会报错
时间空间复杂度:
- 时间复杂度: O(n)
- 空间复杂度: O(n)