贪心算法(LeetCode基础)

贪心算法

[贪心算法(第10~12天)](04.04.01 贪心算法(第 10 ~ 12 天) (datawhalechina.github.io))

简介

通过局部最优解得到整体最优解,或者最优解的近似解

如何判断一个问题可以通过贪心算法求解?

举反例:即最优解可以通过其他算法求解

应用

分发饼干

使用贪心算法的代码解决步骤描述如下:

  1. g l i s t glist glist s l i s t slist slist 进行从小到大排序,使用变量 g i n d e x gindex gindex s i n d e x sindex sindex 分别指向 g l i s t glist glist s l i s t slist slist 初始位置,使用变量 r e s res res 保存结果,初始化为 0 0 0
  2. 对比每个元素 g l i s t [ g i n d e x ] glist[gindex] glist[gindex] s l i s t [ s i n d e x ] slist[sindex] slist[sindex]
    1. 如果 g l i s t [ g i n d e x ] ≤ s l i s t [ s i n d e x ] glist[gindex] \le slist[sindex] glist[gindex]slist[sindex],说明当前饼干满足当前孩子胃口,则答案数量加 1 1 1,并且向右移动 g i n d e x gindex gindex s i n d e x sindex sindex
    2. 如果 g l i s t [ g i n d e x ] > s l i s t [ s i n d e x ] glist[gindex] > slist[sindex] glist[gindex]>slist[sindex],说明当前饼干无法满足当前孩子胃口,则向右移动 s i n d e x sindex sindex,判断下一块饼干是否可以满足当前孩子胃口。
  3. 遍历完输出答案 r e s res res
#分发饼干
def distributeCookies(glist,slist):
    glist.sort()
    slist.sort()

    gindex ,sindex =0,0
    res = 0
    while gindex < len(glist) and sindex < len(slist):
        if glist[gindex] <= slist[sindex]:
            gindex += 1
            sindex += 1
            res += 1
        else:
            sindex += 1

    return res

练习

01柠檬水找零

我们可以记录当前手中的 5 元和 10 元的数量

  1. 每当遇到一位顾客支付 5 元时,我们将 5 元的数量加1
  2. 当遇到一位顾客支付 10 元时,我们先检查手中是否有足够的 5 元,如果没有,则无法找零,直接返回 False,否则将 5 元数量减1,10 元的数量加1
  3. 当遇到一位顾客支付 20 元时,我们先尝试用手中的一张 10 元和一张 5 元找零,如果不行,则尝试用三张 5 元找零,如果还不行,则说明无法找零,直接返回 False。
#找零问题
def lemonadeChange(bills):
    cnt_5, cnt_10 = 0, 0   # 记录当前五元和十元的数量
    for bill in bills:
        if bill == 5:
            cnt_5 += 1
        elif bill == 10:
            if cnt_5 == 0:
                return False
            cnt_5 -= 1
            cnt_10 += 1
        else:   # bill == 20
            if cnt_10 > 0 and cnt_5 > 0:
                cnt_10 -= 1
                cnt_5 -= 1
            elif cnt_5 >= 3:
                cnt_5 -= 3
            else:
                return False
    return True

02分发糖果

  1. 我们可以初始化一个数组 candy,其中的每个元素表示每个孩子分到的糖果数量,默认为 1。

  2. 我们从左到右遍历孩子的评分 ratings,如果当前孩子的评分比左侧孩子高,那么他应该比左侧孩子多分到一个糖果,即 candy[i] = candy[i-1] + 1

  3. 我们再从右到左遍历孩子的评分 ratings,如果当前孩子的评分比右侧孩子高,并且比右侧孩子分到的糖果数量少或相等,那么他应该比右侧孩子多分到一个糖果,即 candy[i] = max(candy[i], candy[i+1] + 1)

  4. 我们计算分发的糖果总数,即 sum(candy)

#奖励糖果
def disCandy(score):
    n = len(score)
    candy = [1] * n                     # 初始化每个孩子分到的糖果数量为 1

    for i in range(1,n):                # 从左到右遍历孩子评分,保证高分孩子多分到糖果
       if score[i] > score[i-1]:
           candy[i] = candy[i-1] + 1

    for i in range(n-2,-1,-1):   # 从右到左遍历孩子评分,保证高分孩子多分到糖果,且满足给低分孩子更多糖果的要求
        if score[i] > score[i+1] and candy[i] <= candy[i+1]:
            candy[i] =candy[i+1] +1
            
    return sum(candy)
  • 21
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Sean7566

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

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

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

打赏作者

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

抵扣说明:

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

余额充值