凑纸币时间复杂度O(1)-python

参加面试的时候看到这道题,当时并没有做出来,很遗憾,功底不够。存了很久一直没发,花了一下午时间做完。

现有i张十元纸币,k张五元纸币,j张两元纸币,购物后要支付n元(i,j,k,n 为整数)。要求编写一个复杂度为O(1)的函数find_solution(i,j,k, n),功能是计算出能否用现在手上拥有的纸币是否足够并能刚好拼凑齐n元,而不需要找零。

首先时间复杂度为O(1),即无论参数如何变化,函数运行时间不变,这里就否定了通过三层循环找到结果。

其次,这里只需要刚好拼凑齐n元,不用计算有多少种方法。
这里想到可以采用借位的方法。

首先这里要找三个规律:

n的个位数是 0 1 2 3 4 5 6 7 8 9
对应的2元纸币张数的个位数为 0,5 3,8 1,6 4,9 2,7 0,5 3,8 1,6 4,9 2,7
对应的5元纸币张数的个位数为 偶数 奇数 偶数 奇数 偶数 奇数 偶数 奇数 偶数 奇数
对应的10元纸币张数的个位数为 0-9 0-9 0-9 0-9 0-9 0-9 0-9 0-9 0-9 0-9

首先从测试代码写起,通过最简单的三重循环找到所有以当前r2,r5,r10可以满足的数值:

def sham1(r2,r5,r10):
	b = set(2*i+5*j+10*k for k in range(r10+1) for j in range(r5+1) for i in range(r2+1))
	return b

接下来是分析,之前的规律表说明数字的个位数决定了最小的2元纸币和5元纸币的张数,因为只有这两个数值相加才能凑出1,3,7,9的个位数,即:

rs2 = [0, 3, 1, 4, 2]  # 0,3,1,4,2 以5为步长。
small2 = rs2[tar % 10-5 if tar 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值