贪心算法
[贪心算法(第10~12天)](04.04.01 贪心算法(第 10 ~ 12 天) (datawhalechina.github.io))
简介
通过局部最优解得到整体最优解,或者最优解的近似解
如何判断一个问题可以通过贪心算法求解?
举反例:即最优解可以通过其他算法求解
应用
分发饼干
使用贪心算法的代码解决步骤描述如下:
- 对 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。
- 对比每个元素
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]:
- 如果 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。
- 如果 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,判断下一块饼干是否可以满足当前孩子胃口。
- 遍历完输出答案 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 元的数量
- 每当遇到一位顾客支付 5 元时,我们将 5 元的数量加1
- 当遇到一位顾客支付 10 元时,我们先检查手中是否有足够的 5 元,如果没有,则无法找零,直接返回 False,否则将 5 元数量减1,10 元的数量加1
- 当遇到一位顾客支付 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分发糖果
-
我们可以初始化一个数组
candy
,其中的每个元素表示每个孩子分到的糖果数量,默认为 1。 -
我们从左到右遍历孩子的评分
ratings
,如果当前孩子的评分比左侧孩子高,那么他应该比左侧孩子多分到一个糖果,即candy[i] = candy[i-1] + 1
。 -
我们再从右到左遍历孩子的评分
ratings
,如果当前孩子的评分比右侧孩子高,并且比右侧孩子分到的糖果数量少或相等,那么他应该比右侧孩子多分到一个糖果,即candy[i] = max(candy[i], candy[i+1] + 1)
。 -
我们计算分发的糖果总数,即
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)