目錄
題目描述:
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;
}
}