这种动态编程算法的时间复杂度是多少?

时间:2019-09-12 17:20:06

标签: algorithm time-complexity

我正在从一本书中学习动态编程解决方案。我了解问题的解决方案,但不确定该书没有提供解决方案的时间复杂性。

我的问题:

给出无限个四分之一(25美分),一角钱(10美分),镍(5美分)和便士(1美分),编写代码以计算表示n美分的方式。

我的分析

每个输入必须经过4个“级别”,即25、10、5,1。 在第一级中,循环将执行n / 25次;在第二级中,循环将执行最多(n / 25)(n / 10)次,而第三级则最多执行(n / 25)(n / 10)(n / 5),最后一级最多执行(n / 25)(n / 10)*(n / 5) n。所以总运行时间为(n / 25)(n / 10)*(n / 5) n +(n / 25)(n / 10)(n / 5)+(n / 25)(n / 10)+ n / 25,即O(N ^ 4)。首先,我不确定我的归纳是否正确。其次,如果我是对的,我想知道是否存在更紧密的联系,因为在每个级别中,我仅计算最大次数而不是平均次数。

解决方案如下:

int makeChange(int n) {
    int[] denoms = {25, 10, 5, l};
    int[][] map = new int[n + l][denoms.length]; // precomputed 
            vals
    return makeChange(n, denoms, 0, map);
}

int makeChange(int amount, int[] denoms, int index, int[][] map) {
    if (map[amount][index] > 0) {//retrieve value
        return map[amount][index];
     }
    if (index >= denoms.length - 1) return 1; // one denom remaining
    int denomAmount denoms[index];
    int ways = 0;
    for (int i= 0; i * denomAmount <= amount; i++) {
        //go to next denom, assuming i coins of denomAmount
        int amountRemaining = amount - i * denomAmount;
        ways += makeChange(amountRemaining, denoms, index + 1, 
             map);
    }
    map[amount][index] = ways;
    return ways;
}

2 个答案:

答案 0 :(得分:2)

编写的算法为O(n 2 )。分析递归函数时,可以将它们分为两部分:

  1. 每个功能完成的工作
  2. 完成工作的次数

然后,只需将这两个数字相乘即可。因为函数结果被缓存在这里,所以缓存中每个值的工作最多只能完成一次。由于缓存的大小为O(n),因此需要O(n)的时间来填充。

对于每个函数完成的工作,有一个while循环经历O(n)迭代。将它们相乘即可得出O(n 2 )的估计值,这是通过进行粗略估计得出的(输入值加倍会导致所需时间大约翻四倍)。

答案 1 :(得分:0)

只需递归考虑即可计算复杂度。为此,只需考虑25个硬币的数量,然后再考虑其他数量。如果T(n,i)显示了以n的最后i个数表示denoms的方式数目,则我们将得到T(n,4) = T(n-25, 3) + T(n - 2 * 25, 3) + ... + T(n - n//25 * 25, 3)n//25表示n的整数除法。现在我们可以分别对1051重复此操作。

因此,要找到复杂性的严格界限,可以假设n25105整除很多次才能得出最坏的情况和严格的分析。

因此,严格的分析是:

T(n,4) = sum_{i=1}^{n/25} T(n-i*25, 3)
T(n,3) = sum_{i=1}^{n/10} T(n-i*10, 2)
T(n,2) = sum_{i=1}^{n/5} T(n-i*5, 1)
T(n,1) = 1

现在,我们可以从下到上进行计算。 T(n,2) = Theta(n/5)T(n,3) = Theta(n/10 * n/5)T(n,4) = Theta(n/25 * n/10 * n/5) = Theta(n^3)。如您所见,最终结果是Theta(n^3),并且渐近分析并未根据n的确切值进行处理,或者被510或{{ 1}}。

此外,您在计算中存在错误,因为您没有考虑代码中的以下条件:

25

最后一次到if (index >= denoms.length - 1) return 1; // one denom remaining 的时间不正确,它是n