[LeetCode] 135. Candy
来源:互联网 发布:fps软件 编辑:程序博客网 时间:2024/05/16 17:04
题目链接: https://leetcode.com/problems/candy/description/
Description
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?
解题思路
注: 下文所说极小值不是数学函数定义的极小值,只是与其有相似的性质,暂且对其命名为极小值。并且,在此处不要求极小值左右相邻的值必须比其大,而只需其小于左侧相邻的值,小于等于右侧相邻的值。上图中五角星所标注的位置即为此文所定义的极小值。
主要思路是找出ratings
中所有的极小值,发给他们一颗糖,并从每一个极小值处,向左向右依次递增糖的数量,直到rating
开始下降停止更新。
这其中有一个关键地方需要注意,就是 rating
相等的两个人挨在一起,糖的数量不需要一样多,并且应该尽可能只给一颗糖,例如:
ratings
[1, 2, 2, 3] ->candies
[1, 2, 1, 2]ratings
[2, 3, 3, 2, 1] –>candies
[1, 2, 3, 2, 1]ratings
[1, 2, 2, 2, 2, 1] –>candies
[1, 2, 1, 1, 2, 1]
详细过程为,对于 ratings
从头扫到尾寻找极小值,首尾单独写出来。每当找到一个极小值,向左向右更新糖的数量,由于寻找极小值时是从左向右扫,所以向左更新可能会遇到被前一个极小值向右更新过的个体,这两个方向的做法有点区别,分开来讲:
向右更新
可以大致分为三种情况:
- 一直单调递增:糖的数量依次加一就可以;
- 先增后平再增:平即是
rating
相等,此时会有两个拐角,第一个拐角还是按照前面糖的数量加一,其后面rating
相等的个体都只给一颗糖,第二个拐角后面继续依次从两颗糖开始递增; - 先增后平再减:因为在找到下一个极小值点时,会更新这种情况的第二个拐点,所以在此处可以与第二种情况一样处理。
向左更新
只用考虑一种情况——单调递增。即使遇到先增后平,也只考虑拐点那一个点,再往前的不需要修改,所以本质也是单调递增。
向左更新的一个主要目的,就是完善前一个极小值点的漏洞,例如上图中,红橙交界点。
算法也很简单,向左遍历,不是递增就终止;否则,判断当前糖的数量是否小于右侧糖的数量加一(递增则从右往左依次加一),若小于则修改为右侧糖的数量加一,否则不变。
具体示例
如上图,ratings
为 [1, 2, 4, 3, 2, 1, 1, 2, 2, 3, 3, 3, 2, 2, 1, 3]
四个极小值点分别为,(1, 1), (6, 1), (13, 2), (15, 1)
- (1, 1) 更新后,糖的数量分别为 [1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
- (6, 1) 更新后,糖的数量分别为 [1, 2, 4, 3, 2, 1, 1, 2, 1, 2, 1, 1, 0, 0, 0, 0]
- (13, 2) 更新后,糖的数量分别为 [1, 2, 4, 3, 2, 1, 1, 2, 1, 2, 1, 2, 1, 1, 0, 0]
- (15, 1) 更新后,糖的数量分别为 [1, 2, 4, 3, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2]
最终,糖的数量分别为 [1, 2, 4, 3, 2, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2],共计 28 颗。
Code
class Solution {public: int candy(vector<int>& ratings) { int size = ratings.size(); vector<int> candies(size, 0); if (size == 0 || size == 1) return size; // 首部单独判断是否为极小值,向右更新糖的数量 if (ratings[0] <= ratings[1]) { candies[0] = 1; int right = 1; while (right < size) { if (ratings[right] > ratings[right - 1]) { candies[right] = candies[right - 1] + 1; } else if (ratings[right] == ratings[right - 1]) { candies[right] = 1; } else { break; } right++; } } // 从第二个开始寻找极小值,向左右两边更新糖的数量 for (int pos = 1; pos < size - 1; ++pos) { if (ratings[pos] < ratings[pos - 1] && ratings[pos] <= ratings[pos + 1]) { candies[pos] = 1; int left = pos - 1; int right = pos + 1; while (left >= 0) { if (ratings[left] > ratings[left + 1]) { if (candies[left + 1] + 1 > candies[left]) candies[left] = candies[left + 1] + 1; } else { break; } left--; } while (right < size) { if (ratings[right] > ratings[right - 1]) { candies[right] = candies[right - 1] + 1; } else if (ratings[right] == ratings[right - 1]) { candies[right] = 1; } else { break; } right++; } } } // 尾部单独判断是否为极小值,向左更新糖的数量 if (ratings[size - 1] <= ratings[size - 2]) { candies[size - 1] = 1; int left = size - 2; while (left >= 0) { if (ratings[left] > ratings[left + 1] && candies[left + 1] + 1 > candies[left]) { candies[left] = candies[left + 1] + 1; } else { break; } left--; } } return accumulate(candies.begin(), candies.end(), 0); }};
- [LeetCode]135.Candy
- 135. Candy Leetcode Python
- [Leetcode] 135. Candy
- [leetcode] 135.Candy
- [leetcode] 135. Candy
- leetcode 135. Candy
- leetcode 135. Candy
- [LeetCode]135. Candy
- LeetCode 135. Candy
- Leetcode 135. Candy
- leetcode.135. Candy
- LeetCode 135. Candy
- [leetcode] 【数组】 135. Candy
- LeetCode-135.Candy
- LeetCode 135. Candy
- Leetcode 135. Candy
- leetcode-135. Candy
- [LeetCode] 135. Candy
- 6章 分类问题、逻辑回归算法
- MAVEN打包jar
- 96. Unique Binary Search Trees
- Rails 技巧库
- sublime text 添加文件忽略
- [LeetCode] 135. Candy
- Hadoop 2.6.0 启动问题 lib/native/libhadoop.so which might have disabled stack guard
- xjoi奋斗群群赛7
- 【设计模式 8】有关设计模式的新体会、新思考
- 目标检测算法中的bounding box regression
- 开源分享 Unity3d客户端与C#分布式服务端游戏框架
- C#基础-058 List集合、HashSet集合、HashTable集合、StringBuilder与String运行效率比较
- 花生问题——百练OJ:2950:摘花生与1928:The Peanuts
- csdn如何转载别人的文章