1. 程式人生 > 其它 >分糖果問題 與 擴充套件(修改條件)

分糖果問題 與 擴充套件(修改條件)

問題描述

一群孩子做遊戲,現在請你根據遊戲得分來發糖果,要求如下:

  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;
    }
}​

擴充套件

上述分糖果題目中,對於分數相同的孩子,分得的糖果無限制,可多可少
現將條件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;
    }
}