算法设计与分析-Week8

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.

解题思路

本题要为小朋友分糖果,每个小朋友有自己的等级,要求每个小朋友都有糖果,且等级较高的小朋友要比旁边的小朋友拿的糖果多,求分出去的糖果最少数量。
从头到尾遍历ratings数组,一共可以分为三种情况:

  1. 后一个小朋友的等级比前一个高,那么分给后一个小朋友的糖果数量是前一个的加一。
  2. 后一个小朋友的等级与前一个相等,那么分给后一个小朋友一个糖果即可。
  3. 后一个小朋友的等级比前一个低,那么分给后一个小朋友一个糖果,且前面的部分小朋友的糖果数量需要加一,这部分小朋友的等级应该是从前往后递减的。但是没有必要每次遇到一个等级较低的小朋友就更新前面的小朋友的糖果数,可以记录下来,直到遇到一个小朋友的等级大于或等于前一个,或者遍历完成,此时再做累加。

整个算法的时间复杂度为\(O(n)\)。

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Solution {
public:
int candy(vector<int>& ratings) {
int n = ratings.size();
int sum = 1;
int prev = 1;
int countDown = 0;
for(int i = 1; i < n; i++) {
if(ratings[i] >= ratings[i-1]) {
if(countDown > 0) {
sum += countDown*(countDown + 1) / 2;
if(countDown >= prev) sum += countDown - prev + 1;
prev = 1;
countDown = 0;
}
prev = ratings[i] == ratings[i-1] ? 1 : (prev + 1);
sum += prev;
}
else countDown++;
}
if(countDown > 0) {
sum += countDown*(countDown + 1) / 2;
if(countDown >= prev) sum += countDown - prev + 1;
}
return sum;
}
};
0%