LeetCode:candy(分派糖果)

目錄

題目描述:

要求示例:

題目分析:

思路一:

思路二:


題目描述:

There are N children standing in a line. Each child is assigned a rating value.
You are giving candies to these children subjected to the following requirements:
Each child must have at least one candy.
Children with a higher rating get more candies than their neighbors.
What is the minimum candies you must give?

有N個孩子站成一排,每個孩子有一個分值。給這些孩子派發糖果,需要滿足如下需求:

  • 1、每個孩子至少分到一個糖果
  • 2、分值更高的孩子比他相鄰的孩子獲得更多的糖果

求至少需要分發多少糖果?

要求示例:

輸入描述:0,1,0
輸出描述:4

輸入示例:5,4,1,1
輸出示例:7

題目分析:

  • 每個孩子至少一個;
  • 分值高的比相鄰的孩子糖果多;

假如輸入:1,2,2,那第一個孩子1個,第二個孩子2個,第三個孩子呢?按題意,分1個就行。也就是至少四個。

思路一:

  • 初始將每個孩子的糖果數都設爲1;
  • 從左向右掃描,保證一個方向上分數更大的糖果更多;
  • 從右向左掃描,保證另一個方向上分數更大的糖果更多。
import java.util.Arrays;
public class Solution {
    public int candy(int[] ratings) {
        if(ratings == null || ratings.length == 0) {
            return 0;
        }
        
        //初始將每個孩子的糖果數都設爲1
        int[] count = new int[ratings.length];
        Arrays.fill(count, 1);

        int sum = 0;
        //從左向右掃描,保證一個方向上分數更大的糖果更多
        for (int i = 1; i < ratings.length; i++) {
            if (ratings[i] > ratings[i - 1]) {
                count[i] = count[i-1] + 1;
            }
        }
        //從右向左掃描,保證另一個方向上分數更大的糖果更多
        for (int i = ratings.length - 1; i > 0; i--) {
            sum += count[i];
            //左側分值高於右側,左側糖果數不多於右側
            if (ratings[i] < ratings[i - 1] && count[i] >= count[i-1]) {
                //左側糖果數等於右側糖果數+1
                count[i-1] = count[i]+1;
            }
        }

        sum += count[0];
        return sum;
    }
}

思路二:

  • 從頭開始,第一個小朋友給一個糖果,若是升序,則後面小朋友的糖果數依次+1,一直遇到降序。
  • 遇到降序怎麼處理?因爲我們需要給儘可能少的糖果,但需要保證降序的最後一個至少有一個糖果。
  • 此時採用貪心策略:先得到降序的位數,用等差求和,公差爲1,算出遞減階段需要給的糖果數,遞減的最後一個人肯定是給1個。
  • 此時還需要注意:遞減開始的小朋友的糖果不能比它的前一個小朋友多,如果多了,那需要額外補給他的前一個小朋友糖果,來滿足題目第二個條件。

例子: 假如輸入序列是 [1,3,5,7,6,5,4,3,2,1], 前四個小朋友糖果數分別爲1,2,3,4。從第五個小朋友開始變成遞減序列。那個第五個小朋友至少分到:6個。可是第四個小朋友7大於第五個小朋友6,但7只有4個糖果而6有6個,顯然不合理,爲滿足題目第二個條件,所以必須給7小朋友補發糖,要補多少個糖果呢?兩個小朋友相差6-4=2個,但是補2個無法滿足要求,所以要補2+1=3個,也就是小朋友7拿到7個,小朋友6拿6個,這才符合題目要求。

public class Solution {
    public int candy(int[] ratings) {
        if (ratings == null || ratings.length == 0) {
            return 0;
        }

        int pre = 1, countDown = 0, total = 1;
        for (int i = 1; i < ratings.length; i++) {
            if (ratings[i] >= ratings[i - 1]) {
                if (countDown > 0) {
                    total += countDown * (countDown + 1) / 2;

                    if (countDown >= pre) {
                        total += countDown - pre + 1;
                    }

                    pre = 1;
                    countDown = 0;
                }

                pre = ratings[i] == ratings[i - 1] ? 1 : pre + 1;
                total += pre;
            } else {
                //逆序位數
                countDown++;
            }
        }

        if (countDown > 0) {
            total += countDown * (countDown + 1) / 2;
            if (countDown >= pre) {
                total += countDown - pre + 1;
            }
        }
        return total;
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章