4

Below is a recursive function to calculate the value of Binomial Cofecient 'C' i.e. Combination ! I wish to understand this code's Time and Space complexity in terms of N and K (Assuming that We are calculating NCK).

public class ValueOfBinomialCofecientC {

static int globalhitsToThisMethod = 0;

    public static void main(String[] args) {
        // Calculate nCk. 
        int n = 61, k = 55;
        long beginTime = System.nanoTime();
        int ans = calculateCombinationVal(n, k);
        long endTime = System.nanoTime() - beginTime;

        System.out.println("Hits Made are : " +globalhitsToThisMethod + " -- Result Is : " + ans + " ANd Time taken is:" + (endTime-beginTime));
    }

    private static int calculateCombinationVal(int n, int k) {
        globalhitsToThisMethod++;
        if(k == 0 || k == n){
            return 1;
        } else if(k == 1){
            return n;
        } else {
            int res = calculateCombinationVal(n-1, k-1) + calculateCombinationVal(n-1, k);
            return res;
        }
    }

}
rustyx
  • 80,671
  • 25
  • 200
  • 267
Aditya Goel
  • 201
  • 1
  • 15
  • What do you think it is? Maybe it's related to the value of `nCk`? How? – amit May 28 '18 at 11:52
  • I think, It might depend upon, how many times the method "calculateCombinationVal" is invoked ?? But, Need to understand it more clearly.. – Aditya Goel May 28 '18 at 11:58
  • This is exponential, try on paper making a tree of the calls you are making and it will be clear. You will also note that many of the nodes of the tree are repeated, which means that by memorizing results you would save a lot of recursive calls – juvian May 28 '18 at 16:48

2 Answers2

1
        Recursive equation : T(n ,k) = C + T(n-1,k-1) + T(n-1,k);
                             where, T(n ,k) = time taken for computing NCK 
                                    C = constant time => for above if-else 
        
        
                  T(n ,k)
                     | --> work done = C =>after 'C' amount of work  function is split --> level-0
         ____________________________________________ 
        |                                            |
    T(n-1,k-1)                                     T(n-1,k)
        | --> C                                      | --> C => Total work = C+C = 2C -->leve1-1
   ____________________________              _______________________
  |                            |            |                       |
T(n-2,k-2)                T(n-2,k-1)      T(n-2,k-1)            T(n-2,k)
      using tree method : total work done at level-2 = 4C => 2*2*C
                                             level-3 = 8C => 2*2*2*C

        max level tree can grow = max(k+1,n-k-1) 
        => T(n ,k) = 2^max(k+1,n-k-1) * C
           let C=1
           => T(n) = 2^max(k+1,n-k+1)

        T(n) = O(2^n) , k < n/2;
             = O(2^k) , k > = n/2;
0

The runtime is, very interestingly, nCk. Recursively, it is expressed as:

f(n,k) = f(n-1,k-1) + f(n-1,k)

Express each term using the combination formula nCk = n!/(k! * (n-k)!). This is going to bloat up the answer if I try to write every step out, but once you substitute that expression in, multiply the whole equation by (n-k)! * k!/(n-1)!. It should all cancel out to give you n = k + n - k.

There probably are more general approaches to solving multi variable recursive equations, but this one is very obvious if you write out the first few values up to n=5 and k=5.

WestaAlger
  • 501
  • 3
  • 12
  • It is actually a bit less, the base case `if (k==1) return n` saves a bit. But the asymptotic behavior for most k is maybe still the same (I am not sure). – Henry Aug 07 '18 at 03:41
  • Hm I crunched the numbers up to 5,5 like I said, and I took those into account. I got O(3c3) = 1, etc. – WestaAlger Aug 07 '18 at 21:20