简体   繁体   English

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

[英]What is the time complexity of this dynamic programming algorithm?

I'm learning dynamic programming solutions from a book. 我正在从一本书中学习动态编程解决方案。 I understand the solution to a question, but I'm not sure of the time complexity of the solution which, the book didn't provide. 我理解问题的解决方案,但我不确定解决方案的时间复杂性,本书没有提供。

My question: 我的问题:

Given an infinite number of quarters (25 cents), dimes (10 cents), nickels (5 cents), and pennies (1 cent), write code to calculate the number of ways of representing n cents. 给定无限数量的季度(25美分),硬币(10美分),镍币(5美分)和便士(1美分),编写代码来计算代表n美分的方式的数量。

My analysis: 我的分析:

Every input must go through 4 "levels", which is 25, 10, 5,1. 每个输入必须经过4个“级别”,即25,10,5,1。 In the first level the loop will execute n/25 time, in the second level the loop will execute at most (n/25) (n/10) times, the third executes at most (n/25) (n/10) (n/5), the last level executes at most(n/25) (n/10)*(n/5) n. 在第一级中,循环将执行n / 25次,在第二级中循环将执行最多(n / 25) (n / 10)次,第三级最多执行(n / 25) (n / 10) (n / 5),最后一级最多执行(n / 25) (n / 10)*(n / 5) n。 So the total running time is (n/25) (n/10)*(n/5) n +(n/25) (n/10) (n/5)+(n/25) (n/10)+n/25 , which is O(N^4). 因此总运行时间为(n / 25) (n / 10)*(n / 5) n +(n / 25) (n / 10) (n / 5)+(n / 25) (n / 10) + n / 25,即O(N ^ 4)。 First I'm not sure if my induction is right. 首先,我不确定我的归纳是否正确。 Second, if I'm right, I wonder if there's a tighter bond since in each level I only calculated the max times instead of the average times. 其次,如果我是对的,我想知道是否有更紧密的联系,因为在每个级别我只计算了最大时间而不是平均时间。

The solution is below: 解决方案如下:

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;
}

The algorithm as written is O(n 2 ). 写入的算法是O(n 2 )。 When you analyze recursive functions, you can separate them into two pieces: 分析递归函数时,可以将它们分成两部分:

  1. The work done by each function 每个职能所做的工作
  2. The amount of times that work is done 工作完成的次数

Then it's just a matter of multiplying those two numbers together. 那么这只是将这两个数字相乘的问题。 Because the function results are being cached here, the work for each value in the cache is going to be done at most once. 因为函数结果在这里被缓存,所以缓存中每个值的工作最多只能完成一次。 Since the cache is O(n) in size, it takes O(n) time to fill. 由于缓存大小为O(n),因此需要花费O(n)时间来填充。

For the work done in each function, there is a while loop that goes through O(n) iterations. 对于在每个函数中完成的工作,有一个循环经历O(n)次迭代。 Multiplying these together gives you an estimate of O(n 2 ), which is born out by doing a crude estimate (doubling the input value results in roughly quadrupling the time taken). 将这些相乘得出O(n 2 )的估计值,这是通过粗略估计而产生的(输入值加倍导致所花费的时间大约翻了四倍)。

Just think recursively to compute the complexity. 只需递归思考计算复杂性。 To do this, just consider the number of 25 coins and then for the others. 要做到这一点,只需考虑25个硬币的数量,然后考虑其他硬币的数量。 If T(n,i) shows the number of ways to represent n with the last i number of denoms , the we will have T(n,4) = T(n-25, 3) + T(n - 2 * 25, 3) + ... + T(n - n//25 * 25, 3) ( n//25 means the integer division of n ). 如果T(n,i)显示用最后idenoms表示n的方式的数量,我们将得到T(n,4) = T(n-25, 3) + T(n - 2 * 25, 3) + ... + T(n - n//25 * 25, 3) denoms T(n,4) = T(n-25, 3) + T(n - 2 * 25, 3) + ... + T(n - n//25 * 25, 3) n//25表示的整数除法n )。 Now we can repeat this for 10 , 5 , and 1 respectively. 现在,我们可以重复这一过程, 105 ,和1分别。

Therefore, to find a tight bound for the complexity, you can suppose n is divisible by 25 , 10 , and 5 many times to get the worst case and tight analysis. 因此,寻找紧密结合的复杂性,你可以假设n是整除2510 ,和5多次获得最坏的情况和严格的分析。

Hence, the tight analysis is: 因此,严格的分析是:

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

Now, we can compute from bottom to top. 现在,我们可以从下到上进行计算。 T(n,2) = Theta(n/5) , T(n,3) = Theta(n/10 * n/5) , and T(n,4) = Theta(n/25 * n/10 * n/5) = Theta(n^3) . 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) As you can see the final result is Theta(n^3) and the asymtotic analysis deos not depned on the exact value of n or that is divisible by 5 , 10 , or 25 . 正如可以看到的最终结果是Theta(n^3)和不depned上的精确值的渐进的分析DEOS n或通过整除51025

Also, you have a mistake in your computation because you did not consider the following condition in the code: 此外,您的计算错误,因为您没有在代码中考虑以下条件:

if (index >= denoms.length - 1) return 1; // one denom remaining 

And the last times to n is not correct and it is 1 . n的最后一次是不正确的,它是1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM