前情提要:
因为本人最近都来刷贪心类的题目所以该题就默认用贪心方法来做。
贪心方法:局部最优推出全局最优。
如果一个题你觉得可以用局部最优推出全局最优,并且没有反例来反驳的话就可以用贪心来试试。
题目思路:
本题主要就是难在,有俩个维度,当前的孩子不仅要跟左边比,还要跟右边比。
可能我们一开始就想遍历孩子,让当前孩子先跟左边比,然后再跟右边比。
其实这样同时比的话,肯定会顾此失彼。要么左边比右边大,但是糖果数量没有增加,不论怎样都有点问题。
所以对于这样有俩个维度上的问题,我们应该先统一处理好一个维度,再去处理另一个维度。
那本题该怎么处理呢?
所以本题 我们首先让当前孩子与左孩子对比 如果当前孩子比左孩子评分高 则糖果加一。
此时局部最优:只要当前孩子评分比左边大,当前的孩子就多一个糖果,
全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果。
然后我们再让当前孩子与右孩子比较 如果当前孩子比右孩子大 则糖果加一。
具体代码有不少细节,我们放在代码中讲。
最终代码:
class Solution {
public int candy(int[] ratings) {
//定义一个糖果数量的数组
int [] candySum = new int [ratings.length];
Arrays.fill(candySum,1);
//首先让当前孩子与左孩子对比 如果比左孩子的评分高,那么就比左孩子多一个糖果
for(int i = 1;i < ratings.length;i ++){
if(ratings[i] > ratings[i - 1]){
candySum[i] = candySum[i - 1] + 1;
}
}
//然后让当前孩子与右孩子对比
//注意这里是倒序的 为什么是倒序呢 因为当前孩子与右孩子作对比时 是先需要我右孩子的结果
//因为一旦我当前孩子比右孩子大一 我是要在我右孩子的基础上加1嘛 所以这里是从后往前遍历
for(int i = ratings.length - 2;i >= 0;i --){
if(ratings[i] > ratings[i + 1]){
//这里为什么取最大值
//第一种情况 当前孩子只比右大 没有比左大 那么当前孩子的糖果就是取右边孩子糖果加1
//第二种情况 当前孩子比左右都大 那么此时就要取最大值 来保证当前孩子的糖果是最多的
//那么又要贪心了,局部最优:取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,保证第i个小孩的糖果数量既大于左边的也大于右边 的。全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。
candySum[i] = Math.max(candySum[i + 1] + 1,candySum[i]);
}
}
int result = 0;
//最终遍历一遍糖果数量数组 求和
for(int i = 0;i < candySum.length;i ++){
result += candySum[i];
}
return result;
}
}
贪心的题目就是这样巧妙,如果第一次做很难想到这样的思路,所以我们要多做多练。
好啦。这一篇博客就到这了,如果你有什么疑问和想法可以打在评论区,或者私信我。
我很乐意为你解答。那么我们下篇再见!