为什么我的解决方案leetcode 322 Coin Change超时

时间:2017-08-23 22:38:05

标签: c++ algorithm

这是我的代码:

class Solution {
    std::unordered_map<int, int> um;
public:
    int coinChange(vector<int>& coins, int amount) {
        if (amount == 0)
            return 0;

        auto it = um.find(amount);
        if (it != um.end())
            return it->second;

        int ret = -1;

        for (int c : coins)
        {
            int n = 1;
            while (true)
            {
                int a = amount - n * c, m = 0;
                if (a < 0)
                    break;
                if (a > 0)
                    m = coinChange(coins, a);
                if (m != -1)
                {
                    if (ret == -1)
                        ret = m + n;
                    else
                        ret = std::min(ret, m + n);
                }
                n++;
            }
        }

        um[amount] = ret;
        return ret;
    }
};

据我所知,它与最受欢迎的解决方案非常相似,它甚至构造了相同的哈希表。但是我在任意输入时都会超时。 我无法在本地发现任何错误。

任何想法可能出错?

编辑:

我包含问题陈述:

您将获得不同面额的金币和总金额。编写一个函数来计算构成该数量所需的最少数量的硬币。如果这笔钱不能由任何硬币组合弥补,则返回-1。

实施例: 硬币= [1,2,5],金额= 11 返回3(11 = 5 + 5 + 1)

方法:

使用动态编程(递归+ memoization)。对于金额,只要金额为正数,就尝试每一枚硬币。对于上面的例子:

S(11) = 1 + S(10) | 2 + S(9) | 3 + S(8) | ... | 11 + S(0) | //try coin 1

        1 + S(9) | 2 + S(7) | 3 + S(5) | ... | 5 + S(1) | //try coin 2

        1 + S(6) | 2 + S(1) //try coin 5

原谅这个问题的混乱,我相信我对上述想法的实施有一些错误,但我很难找到它。

1 个答案:

答案 0 :(得分:0)

稍后编辑:我错了

我注意到C版本的运行时间仍然太高,所以这不是问题。我设法从Leetcode获得了所有测试并发现了问题。

对于测试案例硬币:{3,7,405,436}和金额:8839我的实施将拨打18744855电话,而最受欢迎的电话仅为34486。

这是因为,对于每个硬币,我尝试尽可能多地将其放入数量(while (true)循环),并且在每次尝试之后我进行递归调用。它是这样的(对于coin = {1}和amount = 3):

S(3) = min{1 + S(2), 2 + S(1), 3 + S(0)}

S(2) = min{1 + S(1), 2 + S(0)}

S(1) = min{1 + S(0)}

S(0) = 0

然而,只需尝试一次硬币并让递归调用处理剩下的就足够了,就像流行的解决方案一样:

S(3) = min{1 + S(2)}

S(2) = min{1 + S(1)}

S(1) = min{1 + S(0)}

S(0) = 0

上一个回答:

我已将相同的解决方案移植到C,并且已被接受,因此我认为这是Leetcode基础架构中的一些问题。

int coinChange_(int* coins, int coinsSize, int *um, int amount) {
    if (amount == 0)
        return 0;

    if (um[amount] != 0)
        return um[amount];

    int ret = -1;

    for (int i = 0; i < coinsSize; i++)
    {
        int c = coins[i];
        int n = 1;
        while (true)
        {
            int a = amount - n * c, m = 0;
            if (a < 0)
                break;
            if (a > 0)
                m = coinChange_(coins, coinsSize, um, a);
            if (m != -1)
            {
                if (ret == -1)
                    ret = m + n;
                else
                    ret = m + n < ret ? m + n : ret;
            }
            n++;
        }
    }

    um[amount] = ret;
    return ret;
}

int coinChange(int* coins, int coinsSize, int amount) {
    int *um = calloc(amount + 1, sizeof *um);
    int ret = coinChange_(coins, coinsSize, um, amount);
    free(um);
    return ret;
}