Leetcode | 135分发糖果

老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。

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

每个孩子至少分配到 1 个糖果。
相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?

示例 1:

输入: [1,0,2]
输出: 5
解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。
示例 2:

输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果。
第三个孩子只得到 1 颗糖果,这已满足上述两个条件。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/candy

代码思路:
例如[4,3,2,1,1,0,2,3,2,2,1,2,0]
将序列分成三种情况
下降序列[4,3,2,1],[1,0],[3,2],[2,1],[2,0]
上升序列[0,2,3],[1,2]
平台序列[1,1],[2,2]
对于下降序列从最后面开始计算给糖果的数量,最右边肯定是1,然后依次上升。
对于上升序列,总最左边开始计算给糖果的数量,最左边肯定是1,然后依次上升。
对于平台序列应该全部赋值为1。
三种情况肯定会在左右端点的值上有重复,对于重复情况而言,肯定是有另一种情况对这个点的赋值需要比原来的值大,所以如果要赋的值比原来的值小,则不需要更改。
在如下情况下例子中的三种情况的赋值如下:
下降序列[4,3,2,1],[2,1],[2,1],[2,1],[2,1]
上升序列[1,2,3],[1,2]
平台序列[1,1],[1,1]
然后拼凑起来重复的地方取较大的值。
输入:[4,3,2,1,1,0,2,3,2,2,1,2,0]
输出:[4,3,2,1,2,1,2,3,1,2,1,2,1]

代码如下:

public int candy(int[] ratings) {
		int i=0;
		int n=0;
		int front;
		int count=1;
		int length=ratings.length-1;
		int[] candy=new int[length+1];
		
		while(i<length) {
			n=i;
			if(n+1<=length&&ratings[n+1]<ratings[n]) {
				//遇到了下降序列
			while(n+1<=length&&ratings[n+1]<ratings[n]) {
				n++;
			}
			//找到下降序列的头,front记录搜索到的下降的最右边的位置
			front=n;
			count=1;
			while(n>=i) {
				//从最右边开始赋值,如果比当前值小则不进行赋值
				if(candy[n]<=count) {
					candy[n]=count;
				}
				count++;
				n--;
			}
			//将i变更到下降最右边的位置
			i=front;
			n=i;
			}
			
			if(n+1<=length&&ratings[n+1]==ratings[n]) {
				//遇到了平台序列
			while(n+1<=length&&ratings[n+1]==ratings[n]) {
				n++;
			}
			//找到平台的最右边
			front=n;
			count=1;
			while(n>=i) {
				//对平台的所有元素赋值为1,并且需要原来的值比1小
				if(candy[n]<=count) {
					candy[n]=1;
				}
				n--;
			}
			i=front;
			n=i;
			}
			
			if(n+1<=length&&ratings[n+1]>ratings[n]) {
				//遇到了上升序列
			while(n+1<=length&&ratings[n+1]>ratings[n]) {
				n++;
			}
			//找到上升序列的最右边位置
			front=n;
			count=1;
			while(i<=n) {
				//从最左边的位置依次赋值
				if(candy[i]<count) {
					candy[i]=count;
				}
				count++;
				i++;
			}
			i=front;
			n=i;
			}
		}
		count=0;
		for(i=0;i<=length;i++) {
			count=count+candy[i];
		}
		//算法的不足的补充,对于单一的元素,以上所有步骤都不做熟
		if(length==1) {
			return 1;
		}else {
			return count;
		}
		
    }

日常看结果:

在这里插入图片描述
代码分析:
在上述思路中需要对整个数组遍历三边,第一次是向前搜索下降、上升和平台的范围,第二次是对这个范围内的各个数进行赋值。最后一次是对整个数组的整体求和。所以时间复杂度是O(N)。
空间复杂度上,需要一个和ratings相同大小的candy数组,所以空间复杂都市O(N)。

博主感觉可以更简单一点,思路正在思考,博主也是新手,有什么不对,代码不太简便还行见谅。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值