分糖果经典问题(C++)

题目:

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

  • 每个孩子至少分配到 1 个糖果。
  • 相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

示例 1:

输入:ratings = [1,0,2]
输出:5
解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

示例 2:

输入:ratings = [1,2,2]
输出:4
解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。
     第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。


思考

:   已知分数的个数即为孩子的个数设为n,f(n)表示第n个孩子得的糖果数

  将题目抽象为数学函数 即 f(n)>=1;

如果ratings[n]>ratings[n-1],则f(n)>f(n-1),那我们就让f(n)=f(n-1)+1;

根据以上条件,可以写出如下代码;

//第一次 从左向右遍历,右跟左比较;
int n=ratings.size();//n=分数个数
        vector<int> data(n);//建立一个长度为n的一个数组data用来存储糖果个数;
        int i,sum=0;
        data[0]=1;//给第一个同学一个糖果;
        for(i=1;i<n;i++){
            if(ratings[i]>ratings[i-1])
            data[i]=data[i-1]+1;//如果右边的同学比左边的同学分数高,分数高的比分数低的多一个糖果;
            else//其实应该再分两种情况 =和<;
                                //=可以让data[i]=data[i-1];
                               //<可以让 data[i]=data[i-1]-1;
//但是上述条件只是为了满足分数高的糖果多这个条件;
//却无法保证总和最小,所以干脆让小的糖果数为最小值1;
            data[i]=1;
        }

好了,既然写到这里 我们来举个例子看看代码是否有什么不完善的地方吧

ep:1 2 1     2 1  2   (分数)

         1 2 1      1  1  2     糖果数)

我们发现第一个例子似乎是没有问题的,但是第二个出了点小问题,正确结果应该是2 1 2;

那是因为我们在一开始默认让第一个孩子得到了一个糖果,但是如例子所示,他有可能得到了两个糖果。

我们只让右边跟左边相比较,保证了从左往右看,分数多的糖多,但是相邻是左右都要看。

我们开始第二次遍历,从右往左倒着来,左边的数跟右边比较来保证左边数大的糖多。

只有在左边分数大并且糖少的情况下,让左边的糖比右边多1。

 for(i=n-2;i>=0;i--){
    if(ratings[i]>ratings[i+1]&&data[i]<=data[i+1])
    data[i]=data[i+1]+1;
        }

注意:i的取值范围是n-2;因为它要和右边的比,数组的最后一个为n-1,所以只可以取n-2。

完整代码如下:

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

如有错误,敬请指教

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值