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.

题解

最近实在太忙,没有时间整块去搞AI的系统学习,只能零碎时间刷刷题。这道题其实我最初碰到是当年去Airbnb面试,当时拿到的是二维的9宫格,其他条件类似,当时非常可惜,但是35分钟之呢,代码没有写好,也错过了心仪的offer。现在看来,这个题的解法其实是很发散的。 对于一维的分糖果问题来说,其实最大的坑点在于遍历的时候,遇到相等序列和下降序列,到底减少多少糖果为适宜。
昨天初刷这道题的时候,我用了一个非常傻但是直接的想法,即两趟遍历,第一趟维持第一个人一个糖果,右边比他高,就加一个,遇到相等和下降,就直接置1,继续之前策略。第二遍,反方向,初始置0,前进遇到高的就加1。 这里我一开始一直没有ac的原因是,其实不是盲目的加1,而是应该判断,当前增加后的糖果数,是不是比第一轮的值大,大了加上增量就好,反之,不用加上。下面贴上代码:

class Solution {
public:
    int candy(vector<int>& ratings) {
        int len = ratings.size();
        if (len == 0) return 0;
        if (len == 1) return 1;
        int cur = 1;
        int sum = 1;
        map<int,int> score;
        score[0] = 1;
        for(int i=1;i<len;i++){
            if(ratings[i]>ratings[i-1]){
                cur+=1;
                sum+=cur;
                score[i] = cur;
            }else{
                cur = 1;
                sum+=cur;
                score[i] = cur;
            }
        }
        cur = 0;
        for(int i=len-2;i>=0;i--){
            if(ratings[i]>ratings[i+1]){
                cur+=1;
                if(score[i] < 1 + cur){
                   sum+=(1+cur - score[i]); 
                }else{
                    cur = 0;
                }
                
            }else{
                cur = 0;
                
            }
        }
        return sum;
    }
};

后来仔细想想,代码可以在优化一下,第二轮的时候,直接比较相邻的有增加的两项就好,代码如下:

class Solution {
public:
    int candy(vector<int>& ratings) {
        int len = ratings.size();
        
        vector<int> candy_nums(len,1);
        int sum = 0;
        for(int i=0;i<len-1;i++){
            if(ratings[i+1]>ratings[i]){
                candy_nums [i+1] = candy_nums[i]+1;
            }
        }
        
        for(int i = len-1;i>0;i--){
            if(ratings[i-1]>ratings[i]){
                candy_nums [i-1] = max(candy_nums[i-1],candy_nums[i]+1);
            }
        }
        for(auto num:candy_nums){
            sum+=num;
        }
        return sum;
    }
};

当然可以继续优化,一趟遍历搞定。其实我当初还有个趣味的思路,即把rating值的差异,当做偏序关系,构建有向边,然后利用拓补排序搞定。而且我觉得这个做法,在二维中可能比两遍遍历更加的简单。待我有空,一一补充。

一趟遍历

拓补排序解法

二维场景下的讨论

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值