🚩传送门:牛客题目
力扣题目

题目

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

  • 每个孩子至少分配到 _1_ 个糖果。
  • 相邻两个孩子评分更高的孩子会获得更多的糖果。
  • 请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例 1:

输入:ratings = [1,0,2] 输出:5 解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

解题思路:左右遍历

我们可以将「相邻的孩子中,评分高的孩子必须获得更多的糖果」这句话拆分为两个规则,分别处理。

  • 左规则:NC[130]. 分配糖果 - 图1 时,NC[130]. 分配糖果 - 图2 号学生的糖果数量将比 NC[130]. 分配糖果 - 图3 号孩子的糖果数量多。
  • 右规则:NC[130]. 分配糖果 - 图4 时,NC[130]. 分配糖果 - 图5 号学生的糖果数量将比 NC[130]. 分配糖果 - 图6号孩子的糖果数量多。

🚩先从左至右遍历学生成绩 **ratings**,按照以下规则给糖,并记录在 **left**中:

  1. 将第一个孩子设置成 1 颗糖

    left[0]=1

  2. NC[130]. 分配糖果 - 图7 时,NC[130]. 分配糖果 - 图8 号学生的糖果数量将比 NC[130]. 分配糖果 - 图9 号孩子的糖果数量多 1 个。

    left[i]=left[i-1]+1

  3. NC[130]. 分配糖果 - 图10 时,NC[130]. 分配糖果 - 图11 号学生的糖果数量将设置成 1 个。

    left[i]=1

经过此规则分配后,可以保证所有学生糖数量 满足左规则

🚩再从右至左遍历学生成绩 **ratings**,按照以下规则给糖,并记录在 **right**中:

  1. 将最后一个孩子设置成 Math.max(1,ans[n-1]) 颗糖

    right[n-1]=1

  2. NC[130]. 分配糖果 - 图12 时,NC[130]. 分配糖果 - 图13 号学生的糖果数量将比 NC[130]. 分配糖果 - 图14号孩子的糖果数量多 1 个。

    right[i]=right[i+1]+1

  3. NC[130]. 分配糖果 - 图15时,NC[130]. 分配糖果 - 图16号学生的糖果数量将设置成 1 个。

    right[i]=1

经过此规则分配后,可以保证所有学生糖数量 满足右规则

🚩 最后取 **left****right** 中每个下标的的最大值,求和返回即是最终的结果

节约数组可以优化成一个数组,因为我们只需要**left****right**中的最大值

复杂度分析

时间复杂度: NC[130]. 分配糖果 - 图17 ,其中 NC[130]. 分配糖果 - 图18 是数组 NC[130]. 分配糖果 - 图19 的长度。我们需要遍历两次数组

空间复杂度:NC[130]. 分配糖果 - 图20 ,其中 NC[130]. 分配糖果 - 图21 是数组 NC[130]. 分配糖果 - 图22 的长度。

我的代码

  1. public class Solution {
  2. public int candy (int[] arr) {
  3. int n=arr.length;
  4. if(arr==null||n==0) return 0;
  5. int[]ans=new int[n]; // 分配辅助空间数组
  6. ans[0]=1; // 第一个孩子给1个糖果
  7. // 从左向右,满足右规则
  8. for(int i=1;i<n;i++){
  9. if(arr[i]>arr[i-1])
  10. ans[i]=ans[i-1]+1;
  11. else
  12. ans[i]=1;
  13. }
  14. // 从右向左,满足左规则
  15. for(int i=n-2;i>=0;i--){
  16. if(arr[i]>arr[i+1])
  17. ans[i]=Math.max(ans[i+1]+1,ans[i]); // 取ans[i+1]+1和ans[i]中的最大值
  18. else
  19. ans[i]=Math.max(1,ans[i]); // 取1和ans[i]中的最大值
  20. }
  21. return Arrays.stream(ans).sum(); // 返回求和结果
  22. }
  23. }