python - 如何计算硬币找零问题中的发生次数
问题描述
我有一堆[5, 10, 20, 50, 100, 500]
给定值的现金票据x
,找到总和为该值的最少可能票据,然后返回数组中这些票据的出现。我们假设我们只能接收可被整除的数字min(cash) = 5
例如
x = 5:
return [1, 0, 0, 0, 0, 0]
以最少的笔记量接收 5 个,并且 5 个出现一次。
另一个例如
x = 1000
return [0, 0, 0, 0, 0, 2]
因为最少的音符是两个 500 的。它们出现两次。这应该很容易,而且可能很容易,我想我快到了,但似乎无法绕过最后的障碍。
到目前为止,我的代码是:
def atm(x, cash=[5, 10, 20, 50, 100, 500]):
count_5 = 0
count_10 = 0
count_20 = 0
count_50 = 0
count_100 = 0
count_500 = 0
if x == 5:
return [1, 0, 0, 0, 0, 0]
elif x == 10:
return [0, 1, 0, 0, 0, 0]
elif x == 20:
return [0, 0, 1, 0, 0, 0]
elif x == 50:
return [0, 0, 0, 1, 0, 0]
elif x == 100:
return [0, 0, 0, 0, 1, 0]
elif x == 500:
return [0, 0, 0, 0, 0, 1]
flag = None
for c in cash:
if c < x:
flag = c
temp_balance = round(x - flag, 2)
if flag or temp_balance == 5:
count_5 += 1
if flag or temp_balance == 10:
count_10 += 1
if flag or temp_balance == 20:
count_20 += 1
if flag or temp_balance == 50:
count_50 += 1
if flag or temp_balance == 100:
count_100 += 1
if flag or temp_balance == 500:
count_500 += 1
return [count_5, count_10, count_20, count_50, count_100, count_500]
print(atm(150))
这返回的[1, 1, 1, 1, 1, 1]
结果与我预期的不正确[0, 0, 0, 1, 1, 0]
。我在这里做错了什么以及如何解决这个问题?
我已经部分使用了这个 YouTube视频,但是我没有使用递归。
我也在考虑时间复杂度,但处于创建更有效算法的早期阶段。因此,如果有更好的方法代替所有这些if
elif
陈述,那么我想从中学习。
解决方案
为什么您看到[1, 1, 1, 1, 1]
(全 1)的部分问题是因为您的 if 语句中有错误:
if flag or temp_balance == 100:
这不检查flag is 100 or temp_balance is 100
它是否只是检查 if flag is non-zero OR temp_balance is 100
,每次迭代都会如此。
其他一些问题:
- 您有一个
cash
参数作为输入,但这不一定与您用于跟踪音符数量的变量相关。您应该找到一些方法来根据初始cash
数组跟踪您的笔记。这可以像创建另一个相同长度的数组一样简单,该数组初始化为全 0,用于保存每个位置的现金钞票数量。note_count = [0 for _ in cash]
- 不要试图提取完全匹配的特殊情况。它只会让你的代码更长。
- 您不能对这个问题使用贪心算法。您需要动态编程之类的东西才能正常工作。考虑你的现金价值
cash=[10, 50, 150, 200]
,你就有了x=300
。如果你使用贪心算法,你会记 3 个音符,200 个音符的 1 个音符和 50 个音符的 2 个音符,但你可以用 150 个音符的 2 个音符来做。
时间复杂度(用大 O 表示法表示O(n)
)是关于执行长度如何作为某些输入的一个因素而增长
最典型的案例是n
表示您的算法迭代的项目数(但它可以表示其他东西,例如执行一些按位数学运算的算法的输入的位长度)。如果您的现金系统的上限为某个数字,例如 10,那么您用于查找下一张现金钞票的循环将成为一个常数,因为您需要进行恒定次数的迭代以找到下一张要除以的钞票。事实上,在您的情况下,您在选择纸币方面具有恒定的时间复杂度,因为您已经明确写出了 6 个现金纸币案例。这里可变的是您的输入量,因此您的时间复杂度将取决于将给定量减少到 0 需要多长时间。
时间复杂度与两个操作之间的效率无关
当您谈论if, else if
语句以及如何编写更高效的代码时,您可能会说“一个构造比另一个构造更有效或更快”是正确的,但这不是时间复杂度的含义。时间复杂度是关于执行长度如何作为某些输入的一个因素而增长的。例如,您可以通过使用字典来创建一个更有效的“选择”结构。字典具有恒定的时间访问权限,因此无论字典中有多少项,您的时间访问权限都是O(1)
. 但是,如果您有恒定数量的 if/else 语句,那也是O(1)
因为您的 if/else 语句不会增长。它可能会慢一些,但它的复杂性仍然是不变的。
推荐阅读
- javascript - 如何使用插槽为 Vuetify 数据表中的分组行设置样式?
- javascript - 如何在反应js中使用用javascript编写的热图
- php - 致命错误:未捕获的错误:调用 php 中未定义的函数 mysql_connect()
- javascript - 修改 API 发送的 Javascript 对象
- php - 如何在超类的静态方法中检索子类的静态属性
- javascript - 如果 javascript 数组是对象,那么它是否具有键:值对?
- mongodb - 如何获得未读计数
- batch-file - 相当于 hexdump -ve '1/1 "%.2x"' 的 Windows 批处理
- jenkins - Jenkins Gerrit 报告值插件删除了 Code-review 的值
- spring-boot - 由于遇到无效的字节序标志值,休眠空间 5 无法插入数据