经典算法梳理-贪心算法(python)

基本找零问题

假设商店老板需要找零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

买卖股票的最佳时机 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

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值