问题描述

一群孩子做游戏,现在请你根据游戏得分来发糖果,要求如下:

  1. 每个孩子不管得分多少,起码分到一个糖果。
  2. 任意两个相邻的孩子之间,得分较多的孩子必须拿多一些糖果(若相同则无此限制)
    给定一个数组 arr代表得分数组,请返回最少需要多少糖果。
    要求: 时间复杂度为 O(n);空间复杂度为 O(n)
    数据范围: 1≤n≤100000 ,1≤arr[i]≤1000

解题思路(贪心策略):

注意:若两个孩子得分相同,分配糖果无限制,即不需要保证分数相同(相邻与否),得到的糖果数相同
1、先创建一个长度为arr.length,元素都为1的数组
2、从左往右看:索引值从 0 到length-2,看arr[i] 与 arr[i+1]的关系,如果arr[i]<arr[i+1],则 i+1位置 上的糖果比 i位置 多给一个,即candy[i+1]=candy[i]+1;
3、从右往左看:索引值从 length-1 到 1,看arr[i] 与 arr[i-1]的关系,如果arr[i-1]>arr[i],则 i-1位置 上的糖果要保证比 i位置 上的多,即candy[i-1]=Math.max(candy[i-1],candy[i]+1); 因为candy[i-1]可能已经在“从左往右看”的时候被再次赋值过,这个值有可能比candy[i]大,因此需要进行比较,选出最大的,这样可以保证糖果比左右的都要多,例如:分数序列123451,5就比1+1大
总结:从左往右,保证右边比左边大的时候,糖果数也大;从右往左,保证右边比左边大或相等的情况下,糖果数符合要求

代码:

import java.util.*;
import java.lang.Math;

public class Solution {
    /**
     * pick candy
     * @param arr int整型一维数组 the array
     * @return int整型
     */
    public int candy (int[] arr) {
        // write code here
        int len = arr.length;
        if(len==1) return 0;
        int[] candy = new int[len];
        for(int i=0;i<len;i++){
            candy[i]=1;
        }
        for(int i=0;i<len-1;i++){  //从左往右
            if(arr[i+1]>arr[i]){  //后一个分数更大
                candy[i+1]=candy[i]+1;  //多给个糖果
            }
        }
        for(int i=len-1;i>0;i--){  //从右往左
            if(arr[i-1]>arr[i]){  //前面分数大于后面的,保证前面的糖果数多余后一个的
                candy[i-1]=Math.max(candy[i-1],candy[i]+1);
            }
        }
        int res=0;
        for(int i=0;i<arr.length;i++){
            res+=candy[i];
        }
        return res;
    }
}

分糖果问题java 分糖果问题进阶问题_java

扩展

上述分糖果题目中,对于分数相同的孩子,分得的糖果无限制,可多可少
现将条件2改成,任意两个相邻的孩子之间,得分较多的孩子必须拿多一些糖果,且保证相邻的分数相同的孩子糖果数相同

思路

“从左往右看” 和 “从右往左看”时,添加分数相同的判断

代码

import java.util.*;
import java.lang.Math;

public class Solution {
    /**
     * pick candy
     * @param arr int整型一维数组 the array
     * @return int整型
     */
    public int candy (int[] arr) {
        // write code here
        int len = arr.length;
        if(len==1) return 0;
        int[] candy = new int[len];
        for(int i=0;i<len;i++){
            candy[i]=1;
        }
        for(int i=0;i<len-1;i++){  //从左往右
            if(arr[i+1]>arr[i]){  //后一个分数更大
                candy[i+1]=candy[i]+1;  //多给个糖果
            }else if(arr[i+1]==arr[i]){  //分数相同
                candy[i+1]=candy[i];  //后面与前面糖果数相同
            }
        }
        for(int i=len-1;i>0;i--){  //从右往左
            if(arr[i-1]>arr[i]){  //前面分数大于后面的,保证前面的糖果数多余后一个的
                candy[i-1]=Math.max(candy[i-1],candy[i]+1);
            }else if(arr[i-1]==arr[i]){
                candy[i-1]=Math.max(candy[i-1],candy[i]);
            }
        }
        int res=0;
        for(int i=0;i<arr.length;i++){
            res+=candy[i];
        }
        return res;
    }
}