【leetcode-Python】-贪心-135. Candy

这篇博客讨论了LeetCode中的135. Candy问题,介绍了如何使用贪心算法确保评分高的孩子比两侧邻位孩子获得更多的糖果。文章通过示例解释了题目要求,并提供了Python实现的详细步骤,包括从左往右和从右往左的两次遍历策略,以确保全局最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接

https://leetcode.com/problems/candy/

题目描述

有n个孩子站成一条直线,老师根据每个孩子的表现预先给他们打分并分发糖果。分发糖果的规则为:

(1)每个孩子至少分到1个糖果。

(2)评分更高的孩子必须比他两侧的邻位孩子获得更多的糖果。

请问老师至少需要准备多少颗糖果?

示例

输入:ratings =[1,0,2]

输出:5

分别给三个孩子分发2、1、2颗糖果。

输入:ratings = [1,2,2]

输出:4

分别给三个孩子分发1、2、1颗糖果。第三个孩子得到1颗糖果也是符合题意的。

解题思路

这个问题涉及到数组中当前值和左右两边值的大小比较 ,比较结果会影响当前孩子得到的糖果数量。这种涉及到两处比较的情况,我们一般要先比较一侧,再比较另一侧,在两个方向上进行遍历。开数组candy,candy[i]表示索引为i的小孩得到的糖果。

首先我们先从左往右遍历,保证在右侧且分数更高的孩子能够比左侧的孩子得到更多的糖果。此时就用到“贪心思想“,局部最优策略为:”只要右边孩子的评分比左边孩子大,右边的孩子就多一个糖果“,这样能够达成”全局最优“:相邻的孩子中,评分更高的右边孩子获得比左边孩子更多的糖果。在实现时,由于每个孩子至少有一颗糖,初始化先给每个孩子一颗糖。如果ratings(i)>ratings(i-1),那么candy[i] = candy[i-1] + 1。如果ratings(i)<=ratings(i-1),不进行任何操作(留给下一轮遍历时处理),candy[i]仍为1。

然后从右往左遍历,保证在左侧且分数更高的孩子能够比右侧的孩子得到更多的糖果(反过来进行贪心)。我们直接在candy数组上进行修改,如果ratings(i)>ratings(i+1)(左边孩子的评分比右边孩子的评分大),此时candy[i]的取值有两种选择,一个是candy[i+1] + 1(比右边的孩子多得到一个糖果),一个是维持从左往右遍历时得到的candy[i]结果(上一轮只考虑右边孩子比左边孩子高时得到的糖果数量,可能为1,也可能为candy[i-1]+1)。此时又要用到“贪心思想“,由于分数更高的孩子要比两侧的邻位孩子得到更多的糖果,因此candy[i]的局部最优取值为max(candy[i+1]+1,candy[i]),这样能够保证如果位于索引i的孩子比左右相邻的孩子评分都高,candy[i]的值既大于candy[i-1],又大于candy[i+1]。

两次遍历完成后达到全局最优:相邻的孩子中评分高的孩子获得更多的糖果。

Python实现

class Solution:
    def candy(self, ratings: List[int]) -> int:
        candy = [1 for _ in range(len(ratings))] #初始化每个孩子有一个糖果
        for i in range(1,len(ratings)):#首先从左往右遍历,处理右边孩子比左边孩子评分高的情况
            if (ratings[i] > ratings[i-1]):
                candy[i] = candy[i-1] + 1
        for i in range(len(ratings)-2,-1,-1):
            if (ratings[i]>ratings[i+1]): #从右往左遍历,处理左边孩子比右边孩子评分高的情况
                candy[i] = max(candy[i+1]+1,candy[i])
        return sum(candy)
            
            
        

参考

https://leetcode-cn.com/problems/candy/solution/candy-cong-zuo-zhi-you-cong-you-zhi-zuo-qu-zui-da-/

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值