python 硬币找零问题:这两种方法之间的差异

2ul0zpep  于 2023-01-12  发布在  Python
关注(0)|答案(2)|浏览(336)

我在CS50的pset6中用python实现了硬币兑换问题,当我第一次处理这个问题时,我使用的算法是:

import time

while True:
    try:
        totalChange = input('How much change do I owe you? ')
        totalChange = float(totalChange)  # check it it's a valid numeric value
        if totalChange < 0:
            print('Error: Please enter a positive numeric value')
            continue
        break
    except:
        print('Error: Please enter a positive numeric value')
start_time1 = time.time()
change1 = int(totalChange * 100)  # convert money into cents
n = 0
while change1 >= 25:
    change1 -= 25
    n += 1
while change1 >= 10:
    change1 -= 10
    n += 1
while change1 >= 5:
    change1 -= 5
    n += 1
while change1 >= 1:
    change1 -= 1
    n += 1

print(f'Method1: {n}')

print("--- %s seconds ---" % (time.time() - start_time1))

看了动态规划的讲座后,我想把它实现到这个问题上。这是我的尝试:

while True:
    try:
        totalChange = input('How much change do I owe you? ')
        totalChange = float(totalChange)  # check it it's a valid numeric value
        if totalChange < 0:
            print('Error: Please enter a positive numeric value')
            continue
        break
    except:
        print('Error: Please enter a positive numeric value')
start_time2 = time.time()

change2 = int(totalChange*100)
rowsCoins = [1,5,10,25]
colsCoins = list(range(change2 + 1))
n = len(rowsCoins)
m = len(colsCoins)
matrix = [[i for i in range(m)] for j in range(n)]

for i in range(1,n):
    for j in range(1,m):
        if rowsCoins[i] == j:
            matrix[i][j] = 1
        elif rowsCoins[i] > j:
            matrix[i][j] = matrix[i-1][j]
        else:
            matrix[i][j] = min(matrix[i-1][j], 1 + matrix[i][j-rowsCoins[i]])

print(f'Method2: {matrix[-1][-1]}')

print("--- %s seconds ---" % (time.time() - start_time2))

当我运行程序时,它给出了正确的答案,但需要的时间要长得多。
1.我该如何调整第二段代码,使其正确地实现动态编程?我的问题是从矩阵的左上角而不是右下角开始循环吗?
1.对于我写的每一段代码(以及动态编程的正确实现),算法的时间复杂度是多少?我猜想对于第一段代码,它遵循O(n^4),对于第二段代码,它遵循O(n*m),而动态编程的正确实现应该是O(n),我这样想对吗?
任何有助于更好地理解这些算法的帮助都是非常感谢的。

s5a0g9ez

s5a0g9ez1#

我认为这两个算法基本上都是O(n)。
n在本例中是输入数字的大小。
在第一个算法中,它不是O(n^4),因为这意味着你有4个嵌套循环循环n次,相反,你有4个顺序运行的循环,如果它们根本没有修改change1,那可能是O(4n),这与O(n)是一样的。
在第二个算法中,变量名的选择会让事情变得有点混乱。n是一个常量,m基于输入的大小,所以通常称为n。因此,如果我们将n重命名为c,将m重命名为n,则得到O(c*n),这也与O(n)相同。
这里的关键点是对于任何特定的n和O(n)算法不一定比O(n^2)算法。大O符号只是描述了所做的工作量如何随输入的大小而变化。它所要说的是,随着n变大,O所花费的时间O(n)算法的时间增长比O(n^2)算法的时间增长要慢,所以对于一些足够大的n,复杂度较低的算法会更快。

rsl1atfo

rsl1atfo2#

我该如何调整第二段代码,使其正确地实现动态编程?我的问题是从矩阵的左上角而不是右下角开始循环吗?
恕我直言,这个问题不适合动态规划,所以很难实现正确的dp。检查一个贪婪的解决方案https://github.com/endiliey/cs50/blob/master/pset6/greedy.py,这应该是最好的解决方案。
对于我编写的每个代码(以及动态编程的正确实现),算法的时间复杂度是多少?
基本上你的两个代码都应该是O(n),但这并不意味着它们有相同的时间复杂度,正如你所说,dp解要慢得多,这是因为它们有不同的因子(比率),例如4n0.25n都是O(n),但它们有不同的时间复杂度。
贪婪解的时间复杂度应该是O(1)

相关问题