1. 程式人生 > >【LeetCode 135】Candy

【LeetCode 135】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?

題意:給排成一排的小孩發糖,小孩身高有高有矮。對於任何一對相鄰的小孩,兩者相對較高的那個
必須得到比矮個更多的糖。此外必須保證每個人至少得到一塊糖。
求解所需要準備的糖果總數。

Example 1:
Input: [1,0,2]
Output: 5
Explanation: You can allocate to the first, second and third child with 2, 1, 2 candies respectively.

Example 2:
Input: [1,2,2]
Output: 4
Explanation: You can allocate to the first, second and third child with 1, 2, 1 candies respectively.
             The third child gets 1 candy because it satisfies the above two conditions.

思路:對於任何一個小孩,他得到的糖要比左右比他矮的小孩的糖更多。這個問題其實與2D蓄水池問題類似,都是和左右比較。所以應該想到從左到右、從右到左各遍歷一遍的方法。此外因為本題僅僅是和相鄰元素對比,所以單調棧用處不大。

發糖的難點其實是當兩相鄰小孩等高時的情況,這時兩人分配的糖果是存在所有可能性的。

先從左到右遍歷,根據rating的大小盡可能少的發糖,即從左到右的發糖只需要滿足兩點:         每個小孩至少一塊糖(所有小孩初始化1塊糖);         左邊小孩較矮的話,右邊小孩的糖數比他多一個。  任何更少的糖果都無法滿足這兩點。再從右到左進行修正,這時候只要滿足一點:         右邊小孩較矮的話,左邊小孩的糖數比他多一個。

任何更少的糖果也都無法滿足這一點。兩次遍歷的結合就是題設條件,而且是最低滿足。

int candy(vector<int>& ratings) {
	int len = ratings.size();
	vector<int> candy(len, 1);
	//left-->right
	for (int i = 1; i<len; i++) {
		if (ratings[i]>ratings[i - 1])
			candy[i] = candy[i - 1] + 1;
	}
	//right-->left and sum
	int sum = candy[len - 1];
	for (int i = len - 2; i >= 0; i--) {
		if (ratings[i]>ratings[i + 1] && candy[i] <= candy[i + 1])
			candy[i] = candy[i + 1] + 1;
		sum += candy[i];
	}
	return sum;
}