LeetCode OJ:Candy

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?

算法思想:

定义数组candy保存第i个孩子分到的糖果数,初始化全为1

找到等级向量数组中最小的元素,从数组中最小的元素开始

1、先往后遍历找到递增顺序的最大的元素,并依次向上累加,最小的元素candy[i]为1,右边比它大的元素candy[i+1]为2,以此类推

2、然后从最大的元素后一个元素(肯定比最大的这个元素小或者相等)开始,向后找到递减顺序最小的元素,如果下标值大于数组长度,退出循环。

以这个最小的元素作为基准点,向左依次向上累加,注意当递减到这个最大元素时,一定是取这个元素当前的值和依次递减累加求的的值得最大值,

否则值取得小了,前面的依次递增顺序求得的值就被破坏了。然后以这个最小元素开始,转入1执行;

3、再往前遍历找到递减顺序最大的元素,并依次向上累加;

4、然后从最大的元素前一个元素(肯定比最大的这个元素小或者相等)开始,向前找到递减顺序最小的元素,如果下标小于0,退出循环;

以这个最小元素作为基准点,向右依次向上累加,然后从这个最小元素开始,转入3执行;

最后将candy数组遍历求和,即得最小的糖果数。

class Solution{
public:
	int ajustRight(vector<int> &ratings,int *candy,int k,int n){//向右递增顺序调整,返回的是最大元素的后一个元素
		int i=k+1;
		while(i<n&&ratings[i]>ratings[i-1]){
			candy[i]=candy[i-1]+1>candy[i]?candy[i-1]+1:candy[i];
			i++;
		}
		return i;
	}
	int ajustLeft(vector<int> &ratings,int *candy,int k){//向左递增顺序调整,返回最大元素前一个元素
		int i=k-1;
		while(i>=0&&ratings[i]>ratings[i+1]){
			candy[i]=candy[i+1]+1>candy[i]?candy[i+1]+1:candy[i];
			i--;
		}
		return i;
	}
	int findLMin(vector<int> &ratings,int k){//向左找最小的元素
		int i=k;
		while(i-1>=0){
			if(ratings[i-1]<ratings[i])i--;
			else break;
		}
		return i;
	}
	int findRMin(vector<int> &ratings,int k,int n){//向右找最小的元素
		int i=k;
		while(i+1<n){
			if(ratings[i+1]<ratings[i])i++;
			else break;
		}
		return i;
	}
	void ajust(vector<int> &ratings,int *candy,int k,int n){
		candy[k]=1;
		int t=k,h,minV;
		while(1){
			h=ajustRight(ratings,candy,t,n);//向右递增调整
			if(h>=n)break;
			minV=findRMin(ratings,h,n);//找到右边最小元素
			candy[minV]=1;
			ajustLeft(ratings,candy,minV);//向左递增调整
			t=minV;
		}
		t=k;
		while(1){
			int h=ajustLeft(ratings,candy,t);//向左递增调整
			if(h<0)break;
			minV=findLMin(ratings,h);//找到左边最小元素
			candy[minV]=1;
			ajustRight(ratings,candy,minV,n);//向右递增调整
			t=minV;
		}
	}
	int candy(vector<int> &ratings){
		int minR=0x7fffffff;
		int n=ratings.size();
		int *candy=new int[n];
		for(int i=0;i<n;i++)candy[i]=1;
		int index;
		for(int i=0;i<n;i++){
			if(minR>=ratings[i]){
				minR=ratings[i];
				index=i;//找寻最小元素下标
			}
		}
		ajust(ratings,candy,index,n);
		int sum=0;
		for(int i=0;i<n;i++)sum+=candy[i];
		return sum;
	}
};
answer2:
迭代
时间O(n),空间O(n)
class Solution {
public:
    int candy(vector<int> &ratings) {
        const int n=ratings.size();
        vector<int> increment(n);
        //左右各扫描一遍
        for(int i=1,inc=1;i<n;++i){
            if(ratings[i]>ratings[i-1])
                increment[i]=max(inc++,increment[i]);
            else inc=1;
        }
        
        for(int i=n-2,inc=1;i>=0;--i){
            if(ratings[i]>ratings[i+1])
                increment[i]=max(inc++,increment[i]);
            else inc=1;
        }
        
        return accumulate(&increment[0],&increment[0]+n,n);
    }
};

递归 备忘录法
时间O(n),空间O(n)
class Solution {
public:
    int candy(vector<int> &ratings) {
        vector<int> f(ratings.size());
        int sum=0;
        for(int i=0;i<ratings.size();++i)
            sum+=solve(ratings,f,i);
        return sum;
    }
    int solve(const vector<int> &ratings,vector<int>& f,int i){
        if(f[i]==0){
            f[i]=1;
            if(i>0&&ratings[i]>ratings[i-1])
                f[i]=max(f[i],solve(ratings,f,i-1)+1);
            if(i<ratings.size()-1&&ratings[i]>ratings[i+1])
                f[i]=max(f[i],solve(ratings,f,i+1)+1);
        }
        return f[i];
    }
};


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值