如何证明算法的时间复杂度为O(2 ^ n)?

时间:2015-08-09 05:11:39

标签: java algorithm time-complexity

我正在做HackerRank Coin Change

的练习面试问题

我被困住了,我试图理解Solution这个问题。这是这个问题的递归解决方案。(我的评论要理解它)

  public static int numWays(int[] coins, int sumTo) {
   return numWaysWhichCoin(coins, sumTo, 0);
}
private static int numWaysWhichCoin(int[] coins, int sumTo, int whichCoin) {
    if(sumTo == 0) {
        //empty set
        return 1;
    } else if(sumTo < 0) {
        //no way to form a negative sum with positive coin values
        return 0;
    }  else {
        //sumTo is positive 
        //case gone through all the coins but still a positive sum. Impossible
        if(sumTo > 0 && whichCoin == coins.length) {
            return 0;
        }
        //with and without. With, you can keep using the same coin 
        return numWaysWhichCoin(coins, sumTo - coins[whichCoin], whichCoin) + numWaysWhichCoin(coins, sumTo, whichCoin + 1);
    }
}

作者指出该算法在O(2 n )时间复杂度下运行。根据我在面试中的经验,你应该证明你的答案是合理的。

你如何证明这个时间的复杂性?从我之前的工作到显示在O(2 n )时间运行的算法,我会使用递归关系,如(Fibonacci)T(n)= T(n-1)+ T(n-2) )+ c <= 2T(n-1)+ c,
T(1)= d,但我不能得到像这里那样的递归关系。还有另一种方法可以解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

这两个递归调用使它就像一个以2 n速率增长的binaric树。

就复杂性而言,您的算法与Fibonacci递归算法完全相同。因此,您可以查看并找到许多答案和表达式,甚至可以证明为什么递归Fibonacci的大小为2 n。

答案 1 :(得分:1)

假设有R种不同的组合(请求的结果)。 在特定解r中使用的第i个硬币(0 <= i <= M-1)的硬币数(0 <= r <= R-1)是C(i,r)。因此对于0 ... R-1中的每个r,我们有C(0,r)+ C(1,r)+ .... C(M-1,r)= N. 0 ... R-1中每个r的C(i,r)的最大值是max_c(i)= floor(N / Vi)(Vi是硬币i的值),其小于或等于N. 其中i = 0..M-1的c_max(i)之和<= N * M.因此,在所有组合中使用的单个硬币的总数是O(NM)。 你提出的算法只是迭代c_max(i)每个硬币值Vi的单个硬币的所有子组,即O(2 ^(NM))。