题目链接:
题目大意:
设有 N个小孩子排成一条直线, 其中每个孩子都有一个分值, 现要将糖分给这些孩子, 但要确保每个孩子都要分到糖果, 且分值高的孩子分到的糖果要比他旁边的(2个)孩子的多 ; 求出需要分出的糖果的最小数目 ;
解题过程:
(1) 根据题意, 首先想到可以利用序列(也即 那些孩子的分值)中的 "坑", 即那些比两边的值都要小的点(也即 孩子), 因为这样的点需要分到的糖果必然可以是 1 ;
(2) 那么在遍历序列的过程中每遇到一次这样的点就说明有一段 "上坡"(也即 后一个总不小于前一个的子序列) ; 从而对每一段 "上坡" 进行处理即可 ;
(3) 但是很快发现算漏了 "下坡" 的情况, 即 "坑" 的深度可能大于 1 ; 这时需要考虑反向的情况, 后发现只需要进行反向的同样的处理(但是不能影响第一次遍历时得到的规律) ;
(*) 注: 看过网上的答案之后, 才发现 ... 题目中只说了 "分值高的孩子分到的糖果要比他旁边的(2个)孩子的多" 而并没有说到 分值相同的相邻孩子间的关系, 所以为了最小化需要分出的糖果, 对于分值相同的相邻的孩子, 如果可以, 应尽量让孩子分到的糖果保持在最小值 1 ... ;
代码如下:
class Solution { public: using Ratings = vector<int>; using Candys = vector<int>; int candy(vector<int>& ratings) { Candys candys(ratings.size()); for (auto & c : candys) { c = 1; } candys[0] = 1; for (size_t i = 1; i < ratings.size(); i++) { auto prev = ratings[i - 1]; auto curr = ratings[i]; if (prev < curr) { candys[i] = candys[i - 1] + 1; } else if (prev == curr) { // 不需要处理, 参见 解题过程(*) } } for (size_t i = ratings.size() - 1; i > 0; i--) { auto prev = ratings[i - 1]; auto curr = ratings[i]; if (prev > curr) { candys[i - 1] = max(candys[i - 1], candys[i] + 1); } else if (prev == curr) {
} } int ret = 0; for (auto c : candys) { ret += c; } return ret; }};// 不需要处理, 参见 解题过程(*)
Runtime: 26 ms