[LeetCode] 135. 分发糖果
题目链接 : https://leetcode-cn.com/problems/candy/
题目描述:
老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分。
你需要按照以下要求,帮助老师给这些孩子分发糖果:
- 每个孩子至少分配到 1 个糖果。
- 相邻的孩子中,评分高的孩子必须获得更多的糖果。
那么这样下来,老师至少需要准备多少颗糖果呢?
示例:
示例 1:
输入: [1,0,2]
输出: 5
解释: 你可以分别给这三个孩子分发 2、1、2 颗糖果。
示例 2:
输入: [1,2,2]
输出: 4
解释: 你可以分别给这三个孩子分发 1、2、1 颗糖果.
第三个孩子只得到 1 颗糖果,这已满足上述两个条件。
思路:
思路一:
我们先找从左到右满足最少的糖果, 再找从右到左的, 最后取两边都满足的值(就是最大值)
大家可以自行优化一下!
思路二:只需扫一遍数组
如何判断i位置需要多少糖果, 我们需要处理有三种情况:
ratings[i - 1]==ratings[i], 那么我们只需要1糖果

ratings[i - 1] < ratings[i], 那么我们只需要比前一个多一块糖果

ratings[i - 1] > ratings[i], 那么我们不知道如何判断了比如:

但是, 如果知道递减的个数, 我们就能判断最少的糖果了

所以我们保证, 递减序列,是从 1开始加的(方向加),
再举个例子:
如何判读?的糖果多少, 我们发现ratings是3 - 2递减的,递减序列个数des_num为2,我们反向加,
有公差为1的求和公式\(首项尾项项数\frac{(首项 + 尾项) * 项数}{2}\),所以我们先假设rating在等于4时候也是满足等差的,所以 有\(\frac{( 1 + des\_num ) * des\_num}{2} = \frac{(1 + 2) * 2}{2}\) 糖果,所以ratings是3 - 2对于的糖果说2 - 1
但是还有一种可能, 如下图所示

大家在根据代码理解理解, 如果还有不明白的,可以提出来!
代码:
思路一:
def candy(self, ratings) -> int:
n = len(ratings)
if n == 0: return 0
left_to_right = [1] * n
right_to_left = [1] * n
# 找从左到右满足条件的
for i in range(1, n):
if ratings[i] > ratings[i - 1]:
# 保证从左到右的最少个数
left_to_right[i] = left_to_right[i - 1] + 1
# print(left_to_right)
# 找从右到左满足条件的(同时要符合从左到右)
for i in range(n - 2, -1, -1):
if ratings[i] > ratings[i + 1]:
# 保证从左到右也满足, 同时也满足从右到左
right_to_left[i] = max(left_to_right[i], right_to_left[i + 1] + 1)
# print(right_to_left)
res = 0
# 选这个位置最大值
for i in range(n):
res += max(left_to_right[i], right_to_left[i])
return res
优化思路一:
class Solution:
def candy(self, ratings: List[int]) -> int:
n = len(ratings)
if n == 0: return 0
candy_nums = [1] * n
for i in range(1, n):
if ratings[i] > ratings[i - 1]:
candy_nums[i] = candy_nums[i - 1] + 1
for i in range(n - 1, 0, -1):
if ratings[i - 1] > ratings[i]:
candy_nums[i - 1] = max(candy_nums[i - 1], candy_nums[i] + 1)
return sum(candy_nums)
java
class Solution {
public int candy(int[] ratings) {
if (ratings == null || ratings.length == 0) return 0;
int n = ratings.length;
int[] candy_nums = new int[n];
Arrays.fill(candy_nums, 1);
for (int i = 1; i < n; i++) {
if (ratings[i] > ratings[i - 1]) candy_nums[i] = candy_nums[i - 1] + 1;
}
for (int i = n - 1; i > 0; i--) {
if (ratings[i - 1] > ratings[i]) candy_nums[i - 1] = Math.max(candy_nums[i - 1], candy_nums[i] + 1);
}
int res = 0;
for (int i = 0; i < n; i++) res += candy_nums[i];
return res;
}
}
思路二:
class Solution:
def candy(self, ratings: List[int]) -> int:
res = 1
# 先前值
pre = 1
# 递减长度
des_num = 0
for i in range(1, len(ratings)):
if ratings[i] >= ratings[i - 1]:
if des_num > 0:
# 求和公式
res += ((1 + des_num) * des_num) // 2
# 递减长度比先前值大,所以我们要把先前值补充
if pre <= des_num: res += (des_num - pre + 1)
pre = 1
des_num = 0
if ratings[i] == ratings[i - 1]:
pre = 1
else:
pre += 1
res += pre
else:
des_num += 1
# print(des_num)
if des_num > 0:
res += ((1 + des_num) * des_num) // 2
if pre <= des_num: res += (des_num - pre + 1)
return res
java
class Solution {
public int candy(int[] ratings) {
int res = 1;
int pre = 1;
int des_num = 0;
for (int i = 1; i < ratings.length; i++) {
if (ratings[i] >= ratings[i - 1]) {
if (des_num > 0) {
res += ((1 + des_num) * des_num) / 2;
if (des_num >= pre) res += (des_num - pre + 1);
pre = 1;
des_num = 0;
}
pre = ratings[i - 1] == ratings[i] ? 1 : pre + 1;
res += pre;
} else des_num++;
}
if (des_num > 0) {
res += ((1 + des_num) * des_num) / 2;
if (des_num >= pre) res += (des_num - pre + 1);
}
return res;
}
}
[LeetCode] 135. 分发糖果的更多相关文章
- Java实现 LeetCode 135 分发糖果
135. 分发糖果 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分. 你需要按照以下要求,帮助老师给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果. ...
- leetcode 135分发糖果
这是一道hard题,不好想,但最后还是想出来了,私以为还是根据一些思想方法自己想出来做法印象比较深刻,其次看人家的做法思想自己写代码,其次看代码理解默写,其次直接抄代码: 首先,给每个孩子都发一个糖果 ...
- LeetCode 135——分发糖果
1. 题目 2. 解答 初始化左序奖赏全为 1,从左往右遍历,如果右边的人评分比左边高,右边奖赏比左边奖赏增 1. 初始化右序奖赏全为 1,从右往左遍历,如果左边的人评分比右边高,左边奖赏比右边奖赏增 ...
- LeetCode:135. 分发糖果
LeetCode:135. 分发糖果 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分. 你需要按照以下要求,帮助老师给这些孩子分发糖果: 每个孩子至少分 ...
- Leetcode 135.分糖果
分发糖果 老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分. 你需要按照以下要求,帮助老师给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果. 相邻的孩 ...
- 【LeetCode】分发糖果
[问题]老师想给孩子们分发糖果,有 N 个孩子站成了一条直线,老师会根据每个孩子的表现,预先给他们评分. 你需要按照以下要求,帮助老师给这些孩子分发糖果: 每个孩子至少分配到 1 个糖果.相邻的孩子中 ...
- [Swift]LeetCode135. 分发糖果 | Candy
There are N children standing in a line. Each child is assigned a rating value. You are giving candi ...
- [LeetCode] Candy (分糖果),时间复杂度O(n),空间复杂度为O(1),且只需遍历一次的实现
[LeetCode] Candy (分糖果),时间复杂度O(n),空间复杂度为O(1),且只需遍历一次的实现 原题: There are N children standing in a line. ...
- LeetCode:分发饼干【455】
LeetCode:分发饼干[455] 题目描述 假设你是一位很棒的家长,想要给你的孩子们一些小饼干.但是,每个孩子最多只能给一块饼干.对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的 ...
随机推荐
- BZOJ 4597: [Shoi2016]随机序列 线段树 + 思维
Description 你的面前有N个数排成一行.分别为A1, A2, … , An.你打算在每相邻的两个 Ai和 Ai+1 间都插入一个加号或者 减号或者乘号.那么一共有 3^(n-1) 种可能的表 ...
- Shell中Bash的基本功能(二)
1 历史命令 1)历史命令的查看[root@localhost ~]# history [选项] [历史命令保存文件]选项:-c: 清空历史命令-w: 把缓存中的历史命令写入历史命令保存文件.如果不手 ...
- Kubernetes Deployment故障排除图解指南
个人K8s还在学习中,相关博客还没有写,准备学第二遍再开始学,发现这篇文章挺好,先转载一下. 原创: 白明的赞赏账户 下面是一个示意图,可帮助你调试Kubernetes Deployment(你可以 ...
- 源码阅读-SwiftyJSON
最后更新:2018-03-19 一.说在前面的话: SwiftyJSON 作为一个 swift 的解析库, 在 Swift4 之前备受欢迎, 目前(2018.3.19) 已经有 1.6w+ Star ...
- hive里面union all的用法记录
UNION用于联合多个select语句的结果集,合并为一个独立的结果集,结果集去重. UNION ALL也是用于联合多个select语句的结果集.但是不能消除重复行.现在hive只支持UNION AL ...
- ali之mtl平台学习
摩天轮平台可以进行无线测试.设备借用.打包发布.线上监控等功能. 无线测试包括:mock测试.真机适配.代码审查.验收报告等. mock测试类似于fiddler,主要用于接口查看,可以查看请求,返回串 ...
- Hive、Spark优化案例
一.Join原则 将条目少的表/子查询放在Join的左边.原因:在Join的reduce阶段,位于Join左边的表的内容会被加载进内存,条目少的表放在左边,可以减少发生内存溢出的几率. 小表关联大表: ...
- 2017年广东省ACM省赛(GDCPC-2017)总结
今年第一次参加省赛(也是第一次参加这类比赛),既有点惊喜又有点紧张,前一晚没有怎么睡好,有点怕今年打铁,虽然说大一打铁也说的过去,可是谁也不想打铁. 一开始比赛的时候我一开始没有去看题,而是把我们队的 ...
- chrome 调试
https://developers.google.com/web/tools/chrome-devtools/javascript/step-code step over next function ...
- lambda表达式匿名函数
匿名函数是一个“内联”语句或表达式,可在需要委托类型的任何地方使用.可以使用匿名函数来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数. C# 中委托的发展 在 C# 1.0 中,您通 ...