[Leetcode] 135. Candy 解题报告

这篇博客介绍了LeetCode上的135题——Candy,要求根据孩子的评级公平地分配糖果,使得评级高的孩子得到更多糖果。博主首先提出了使用升序排序并遍历分配糖果的初始思路,虽然可行但效率较低。接着,博主提出了一种改进的贪心策略,通过两次扫描(从左到右和从右到左)来确保评级较高的孩子获得更多的糖果,这将时间复杂度降低到O(n),同时保持了O(n)的空间复杂度。文章包含了详细的解题思路和优化后的代码实现。

题目

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?

思路

本题的总体策略还是贪心法。我开始的思路是:将小孩子们按照rating的升序进行排序,然后依次分配糖果:如果他的某个邻居或者两个邻居已经分配糖果了并且他的rating不大于他的邻居的rating(不可能小于的),那么分配和他的邻居相同数目的糖果;如果他的rating高于他的某个邻居,那么分配他的邻居糖果数目+1。如果他的邻居尚未分配糖果,则只给分配1个。这个思路是可行的,但是代码复杂,时间复杂度为O(nlogn),空间复杂度O(n)。

采用两边扫描的方法可以将时间复杂度降为O(n)。具体方法如下:先从左往右扫描一遍,如果后面一个比前面大,那么他分配的就多一颗糖果,否则就是1。但是这样会产生一个情况,就是两个相邻的排名一样,那么后一个还是分一个,但是右面的小孩的rating可能比这个还小,但是仍然分得和这个值一样的糖果,因此还要从右往左再扫描一遍来补偿小的值。这个思路的代码更加精简,时间复杂度是O(n),空间复杂度O(n)。

代码

class Solution {
public:
    int candy(vector<int>& ratings) {
        if (ratings.size() == 0) {
            return 0;
        }
        int len = ratings.size(), ret = 0;
        vector<int> nums(len, 1);
        for (int i = 1; i < len; ++i) {
            if (ratings[i] > ratings[i - 1]) {
                nums[i] = nums[i - 1] + 1;
            }
        }
        for (int i = len - 1; i > 0; --i) {
            if (ratings[i - 1] > ratings[i] && nums[i - 1] <= nums[i]) {
                nums[i - 1] = nums[i] + 1;
            }
            ret += nums[i];
        }
        return ret + nums[0];
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值