LeetCode 的 Coin Change 问题超过了时间限制

Posted

技术标签:

【中文标题】LeetCode 的 Coin Change 问题超过了时间限制【英文标题】:Time Limit Exceeded on LeetCode's Coin Change problem 【发布时间】:2018-10-24 07:32:07 【问题描述】:

我正在尝试解决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 会失败吗?

【问题讨论】:

【参考方案1】:

好像这件作品:

  fewest[i] = 1 + min(
            (fewest[i - coin] for coin in
                [c for c in coins if i - c >= 0]),
            default=math.inf)

检查所有硬币,过滤适当的硬币。

但是您可以对硬币名词进行排序,并且只遍历给定 i 的足够小的名词。

【讨论】:

【参考方案2】:

我意识到列表理解 [c for c in coins if i - c &gt;= 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% 之一:

【讨论】:

但是你又在在每次 i-loop 运行时做过多的工作来制作合格的_coins。正如我所说,尝试在循环之前对硬币进行排序。然后使用while循环或确定最后一个“好”硬币索引

以上是关于LeetCode 的 Coin Change 问题超过了时间限制的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode322. coin-change

LeetCode 518. Coin Change 2

leetcode笔记:Coin Change

LeetCode 的 Coin Change 问题超过了时间限制

leetcode 518. Coin Change 2/硬币找零 2

LeetCode OJ 322. Coin Change DP求解