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