leetcode(力扣)135. 分发糖果 (贪心)

题目描述

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。
你需要按照以下要求,给这些孩子分发糖果:
每个孩子至少分配到 1 个糖果。
相邻两个孩子评分更高的孩子会获得更多的糖果。
请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目 。

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

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

思路分析

本题中你评分再高也不一定能获得多的糖果。
一句话,不关心学生评分,只关心学生的周围情况。

比如 学生 A 和学生B,排队情况 A在 B左。

  • 若A>B 则A学生获得的糖果比B多一个。 -> 设为:左边小规则
  • 若A<B 则B学生获得的糖果比A多一个。 -> 设为:右边小规则

此时如果变成 ABC三个学生,则C需要同时满足 左边小规则和右边小规则。
如果是ABCDEFGHIJK 等这么多学生呢,也就是说,所有学生都必须满足左边小规则和右边小规则。

流程:

  • 设置两个全是1的数组 left 和right,长度等于题目所给ratings ,left存只符合左边小规则下的糖果分发情况,right同理。

  • 从左到右遍历,若 i+1 同学评分高于 i 同学,则left[i+1] = left[i]+1。

  • 同理填充right数组,但是需要从右到左遍历。

  • 最后每一个位置的同学需要同时满足左边小规则和右边小规则。所以 每一个位置取left和right相对位置的最大值。

为什么right需要反向遍历?

没绕进去,这就是一个很简单想通的问题,因为每个数的更新需要依靠右边的值,的所以要右边的值先更新,再更新左边的值。

我做这道题的时候绕进去了,结果就没想通哈哈,蠢得一。

举例:
测试用例:[87,2,1]

反向遍历: 2>1 则评分为2的同学的糖果为 评分为1的同学的糖果数加1。评分为87的同学糖果数为 评分为2的同学的糖果数加1。变成了3,2,1

正向遍历: 87>2,则评分为87的同学糖果数 为 评分为2的同学的糖果数加1,初始为1,1,1。此时变成了2,1,1.。再次扫描到2的时候,评分为2的同学为 评分为1的同学的糖果数+1,糖果数就变成了2,2,1。这时候就发现不对了,还要修改87评分的同学的糖果数。所以正向遍历不行。

完整代码

class Solution:
    def candy(self, ratings: List[int]) -> int:
        left = [1]  * len(ratings) #  i+1 > i
        right = [1] * len(ratings)  # i+1 <i
        count = 0
        for i in range(len(right)-1):
            if ratings[i] < ratings[i+1]:
                left[i+1] = left[i]+1

        for i in range(len(right)-1,0,-1):
            if ratings[i-1] > ratings[i]:
                right[i-1] = right[i]+1
            count += max(left[i],right[i])
        count += max(left[0],right[0])  
        return count
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深度不学习!!

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值