我正在尝试解决Coin Change problem on LeetCode:
我想出了与解决方案中提到的自底向上的动态编程方法相同的方法:
import math
class Solution:
def coinChange(self, coins, amount):
fewest = [0] * (amount + 1)
for i in range(1, amount + 1):
fewest[i] = 1 + min(
(fewest[i - coin] for coin in
[c for c in coins if i - c >= 0]),
default=math.inf)
return fewest[amount] if fewest[amount] < math.inf else -1
这是我用来验证解决方案的一些pytest
测试用例:
def test_1():
assert Solution().coinChange([1, 2, 5], 1) == 1
def test_2():
assert Solution().coinChange([1, 2, 5], 2) == 1
def test_3():
assert Solution().coinChange([1, 2, 5], 3) == 2
def test_4():
assert Solution().coinChange([1, 2, 5], 4) == 2
def test_5():
assert Solution().coinChange([1, 2, 5], 5) == 1
def test_67():
assert Solution().coinChange([1, 2, 5], 6) == 2
assert Solution().coinChange([1, 2, 5], 7) == 2
def test_8():
assert Solution().coinChange([1, 2, 5], 8) == 3
def test_11():
assert Solution().coinChange([1, 2, 5], 11) == 3
def test_no_way():
assert Solution().coinChange([2], 3) == -1
问题是我收到“超过时间限制”错误:
但是,如果我复制此测试用例并在本地运行,我发现该算法仅需0.02s:
import pytest
def test_time_limit_exceeded():
Solution().coinChange(
[205, 37, 253, 463, 441, 129, 156, 429, 101, 423, 311],
6653)
if __name__ == "__main__":
pytest.main([__file__, '--duration', '1'])
导致以下输出:
============================= test session starts ==============================
platform darwin -- Python 3.6.6, pytest-3.8.1, py-1.6.0, pluggy-0.7.1
rootdir: /Users/kurtpeek/GoogleDrive/CodeRust, inifile:
collected 11 items
coin_changing_leetcode2.py ........... [100%]
=========================== slowest 1 test durations ===========================
0.02s call coin_changing_leetcode2.py::test_time_limit_exceeded
========================== 11 passed in 0.07 seconds ===========================
有任何想法为什么LeetCode未能通过该实现?
答案 0 :(得分:1)
似乎这件作品:
fewest[i] = 1 + min(
(fewest[i - coin] for coin in
[c for c in coins if i - c >= 0]),
default=math.inf)
检查所有硬币,过滤适当的硬币。
但是您可以对普通名词进行排序,并且只对给定的i遍历足够小的名词。
答案 1 :(得分:0)
我意识到对于每个[c for c in coins if i - c >= 0]
,列表理解len(coins)
被评估i
次,而对于每个i
,它只需要评估一次。接受了这种稍微重构的解决方案:
import math
class Solution:
def coinChange(self, coins, amount):
fewest = [0] * (amount + 1)
for i in range(1, amount + 1):
eligible_coins = [c for c in coins if i - c >= 0]
fewest[i] = 1 + min(
(fewest[i - coin] for coin in eligible_coins),
default=math.inf)
return fewest[amount] if fewest[amount] < math.inf else -1
尽管如此,它仍然是针对该问题的Python 3解决方案中排在最后10%的位置之一