题目描述

image.png

解题思路

注意此时判断糖果是否多分发一个有2个维度,左边和右边,所以2个维度分开判断。
首先从左到右,局部贪心:右边比左边评分高,那么多分一个,全局贪心:从左至右,评分高的多一个糖果。
从右到左,局部贪心:左边比右边的评分高,那么就分配比右边多一个,注意这里要取两者最大值,因为要保证刚刚左的糖果分配。
先确定右边评分大于左边的情况(也就是从前向后遍历)
此时局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果
局部最优可以推出全局最优。
如果ratings[i] > ratings[i - 1] 那么[i]的糖 一定要比[i - 1]的糖多一个,所以贪心:candyVec[i] = candyVec[i - 1] + 1
如图:
image.png再确定左孩子大于右孩子的情况(从后向前遍历)
遍历顺序这里有同学可能会有疑问,为什么不能从前向后遍历呢?
因为如果从前向后遍历,根据 ratings[i + 1] 来确定 ratings[i] 对应的糖果,那么每次都不能利用上前一次的比较结果了。
所以确定左孩子大于右孩子的情况一定要从后向前遍历!
如果 ratings[i] > ratings[i + 1],此时candyVec[i](第i个小孩的糖果数量)就有两个选择了,一个是candyVec[i + 1] + 1(从右边这个加1得到的糖果数量),一个是candyVec[i](之前比较右孩子大于左孩子得到的糖果数量)。
那么又要贪心了,局部最优:取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,保证第i个小孩的糖果数量即大于左边的也大于右边的。全局最优:相邻的孩子中,评分高的孩子获得更多的糖果。
局部最优可以推出全局最优。
所以就取candyVec[i + 1] + 1 和 candyVec[i] 最大的糖果数量,candyVec[i]只有取最大的才能既保持对左边candyVec[i - 1]的糖果多,也比右边candyVec[i + 1]的糖果多
如图:
image.png

  1. // 两次贪心的策略
  2. // 一次是从左到右遍历,只比较右边孩子评分比左边大的情况。
  3. // 一次是从右到左遍历,只比较左边孩子评分比右边大的情况。
  4. // 这样从局部最优推出了全局最优,即:相邻的孩子中,评分高的孩子获得更多的糖果。
  5. public int candy(int[] ratings) {
  6. int[] candyArray = new int[ratings.length];
  7. // 先每个人分发糖果
  8. Arrays.fill(candyArray, 1);
  9. // 从前向后
  10. for (int i = 0; i < ratings.length - 1; i++) {
  11. if (ratings[i + 1] > ratings[i]) candyArray[i + 1] = candyArray[i] + 1;
  12. }
  13. // 从后向前
  14. for (int i = ratings.length - 2; i >= 0; i--) {
  15. if (ratings[i] > ratings[i + 1]) candyArray[i] = Math.max(candyArray[i], candyArray[i + 1] + 1);
  16. }
  17. int result = 0;
  18. for (int i = 0; i < candyArray.length; i++) {
  19. result += candyArray[i];
  20. }
  21. return result;
  22. }