COINCHANGE:动态编程O(N)复杂性

时间:2016-08-02 20:21:21

标签: java algorithm

我正在尝试解决以下问题:

你会获得一组硬币S.你可以通过多少种方式得出N,假设你的每枚硬币都有无限量。

注意:集合S中的硬币将是唯一的。该问题的预期空间复杂度为O(N)。 请注意,答案可能会溢出。那么,给我们答案%1000007

我使用DP

有以下解决方案
HashMap<Integer, HashMap<Integer, Integer>> memo = new HashMap<>();
public int coinchange2(List<Integer> a, int b) {
    return use(a, 0, b);
}

private int use(List<Integer> a, Integer index, int n) {
    if(memo.containsKey(a.get(index))) {
        if(memo.get(a.get(index)).containsKey(n)) {
            return memo.get(a.get(index)).get(n);
        }
    }
    if(n == 0 && a.get(index)>=0) {
        return 1;
    }
    if((n > 0 && a.get(index) == 0) || n < 0) {
        return 0;
    }
    int nbWays = 0;
    for(int i = index; i < a.size(); i++) {
        nbWays += use(a, i, n - a.get(i))%1000007;
    }

    if(!memo.containsKey(a.get(index))) {
        memo.put(a.get(index), new HashMap<Integer, Integer>());  
    }
    nbWays = nbWays % 1000007;
    memo.get(a.get(index)).put(n, nbWays);
    return nbWays;
}

但我仍然不符合要求: &#34;部分正确答案。让您的解决方案更有效率&#34;

您知道什么可能导致此代码不是O(N)复杂性吗?

2 个答案:

答案 0 :(得分:2)

我很确定你可能会在一个有O(n)的for循环中递归调用use()。在第一次运行中,你调用use()a.size()次,一次为a中的每个索引,所以这至少是O(n ^ 2),对吧?

你可以逐行调试它,也许看看你调用use()多少次?或者甚至现在只需在每次调用use()时递增一个计数器,这样你就可以知道你经历了多少次运行。

这里的所有其他方法都是O(1)(我认为),所以我觉得它必须是那个循环。

答案 1 :(得分:1)

可以在Wikipedia找到变更问题。这里的代码是Python。 Geeks for Geeks具有C / C ++中的解决方案,它在语法上更接近Java。请花时间完全阅读其中一个,以了解解决方案。