[算法分析与设计] leetcode 每周一题: 135. Candy


题目链接:

135. Candy




题目大意:

设有 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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值