文章目录
基本找零问题
假设商店老板需要找零n元钱,钱币的面额有:100元、50元、20元、5元、1元,如何找零使得所需钱币的数量最少?
思路:每一次尽可能用面值最大的钱币。
def give_change(n,money):
m=n
res=[]
for ii in sorted(money,reverse=True):
if n<ii:
continue
if n==0:
break
res+=[ii]*(n//ii)
n=n%ii
if sum(res)==m:
return res
else:
print("cannot give change")
if __name__ == "__main__":
money=[100,50,20,5,1]
print(give_change(125,money))
leetcode 860:柠檬水找零
在柠檬水摊上,每一杯柠檬水的售价为 5 美元。
顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。
每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。
注意,一开始你手头没有任何零钱。
如果你能给每位顾客正确找零,返回 true ,否则返回 false 。
思路:这个题目限制了只能交易5,10,20,所以比较简单,可以直接定义一个临时变量pocket记录口袋里面现在都有哪些面额的钱,然后根据每一个顾客的加入更新pocket同时判断这个顾客能不能找零。
def lemonadeChange(bills):
pocket={5:0,10:0}
for ii in bills:
print(ii,pocket)
if ii ==5:
pocket[ii]+=1
elif ii==10:
if pocket[5]==0:
return False
pocket[5]-=1
pocket[ii]+=1
else:
if pocket[10]==0 and pocket[5]>=3:
pocket[5]-=3
elif pocket[10]>0 and pocket[5]>0:
pocket[5]-=1
pocket[10]-=1
else:
return False
return True
leetcode 455: 分发饼干
`分发饼干
假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i ,都有一个胃口值 gi ,这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j ,都有一个尺寸 sj 。如果 sj >= gi ,我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。
输入: [1,2,3], [1,1]
输出: 1
解释:
你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。
虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。
所以你应该输出1。
思路:一个饼干比如是3,可以满足的孩子为1或者2,那肯定是优先给2,以使得更多数量的孩子被满足,也就是优先满足最贪婪的孩子。写成代码的思路是,找出s列表中所有满足大于g列表的数的数目,这个数目的最大值。
def findContentChildren(g,s):
g.sort(reverse=True)
s.sort(reverse=True)
cc=0
gi=0
si=0
while gi < len(g) and si < len(s):
if g[gi]<=s[si]:
cc=cc+1
si+=1
gi+=1
return cc
leetcode 575: 分糖果
给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。
示例 1:
输入: candies = [1,1,2,2,3,3]
输出: 3
解析: 一共有三种种类的糖果,每一种都有两个。
最优分配方案:妹妹获得[1,2,3],弟弟也获得[1,2,3]。这样使妹妹获得糖果的种类数最多。
思路:优先给妹妹一个每一类糖果但是不能超过总糖果数目的一半。
def distributeCandies(candies):
return min(len(set(candies)), len(candies)/2)
部分背包问题
0-1背包无法使用贪心算法得到最优解,只能得到近似解,部分背包问题可以使用贪心算法得到最优解,只需要将数据按照价值排序然后依次选取直到背包满了即可;
题目:
现在有很多物品(它们是可以分割的),我们知道它们每个物品的单位重量的价值vi和重量wi(分别存在v和w中);如果给你一个背包它能容纳的重量为m,如何使背包里的物品的价值总和最大,输出最大值。
思路:优先放vi最大的物品,如果该物品放完了还有空间,则继续放vi第二大的物品。如果是0-1背包问题有两个思路:一先放vi最大的,放不下的话第二大。二先放最轻的,但是只能得到近似解。
def fractionbag(v,w,m):
vw_dict={}
v_sum=0
for ii in range(len(v)):
vw_dict[v[ii]]=w[ii]
for vi in sorted(v,reverse=True):
if m==0:
break
if m<=vw_dict[vi]:
m=0
v_sum+=vi*m
else:
m-=vw_dict[vi]
v_sum+=vi*vw_dict[vi]
return v_sum
leetcode 435:无重叠区间
给定一个区间的集合,找到需要移除区间的最小数量,使剩余区间互不重叠。
注意:
可以认为区间的终点总是大于它的起点。
区间 [1,2] 和 [2,3] 的边界相互“接触”,但没有相互重叠。
示例 1:
输入: [ [1,2], [2,3], [3,4], [1,3] ]
输出: 1
解释: 移除 [1,3] 后,剩下的区间没有重叠。
思路:想象这些区间现在是你的课程表,你为了上尽可能多的课该怎么做?首先找到结束最早的课,然后看剩下的课,已经和结束最早的课重合的就不要了,没重合的再去找这些里面结束最早的课,直到遍历完了所有的课。代码上表现出来的思路就是,先找到区间第二个值最小的区间,然后把这个区间写到你的课表上去,然后找到和这个最小区间不会重合的所有区间,因为这个区间是最小的嘛,所以那些不会重合的就是起始数值大于最小区间的end的那些区间,在这些区间里面再找最小的,写到课表里面去。。。以此类推。
def eraseOverlapIntervals(intervals):
initial_length=len(intervals)
res=[]
while intervals:
min_intervel=sorted(min([[ii[1],ii[0]] for ii in intervals]))
res.append(min_intervel)
intervals=[ii for ii in intervals if ii[0]>=min_intervel[1]]
return initial_length-len(res)
leetcode 122: 买卖股票的最佳时机 II
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。
设计一个算法来计算你所能获取的最大利润。你可以尽可能地完成更多的交易(多次买卖一支股票)。
注意:你不能同时参与多笔交易(你必须在再次购买前出售掉之前的股票)。
示例 1:
输入: [7,1,5,3,6,4]
输出: 7
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5-1 = 4 。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6-3 = 3 。
思路:最贪心的做法就是尽可能每天都买卖。只要今天比昨天涨了,就盈利。
def maxProfit(prices):
n=len(prices)
maxprofit=0
for ii in range(n-1):
if prices[ii+1]-prices[ii]>=0:
maxprofit+=prices[ii+1]-prices[ii]
return maxprofit