简体   繁体   中英

Binomial Coefficients. Recursion tree. How to avoid calculating same values multiple times

I am working with my program called BinomialCoefficients .

I did a box trace on C(5,3) and it returns 10 which is correct, but I noticed that in my full recursion tree for C(5, 3) , the value C(3, 2) is evaluated 2 times, and C(2, 1) is evaluated 3 times.

What could be a modification so it avoids computing the same values multiple times?

Here is just the function to show context.

public static int C(int n, int k) {
   if(k>n)
      return 0;
   else if(k==0 || k==n)
      return 1;
   else
      return C(n-1, k-1)+C(n-1, k);
  }

One modification would be to use the multiplicative formula . But you'd have to consider integer overflow.... ( Edit: Have a look at what @ ajb said in the comment)

I'd suggest using a Map for caching result:

Map<String, Integer> cache = new HashMap<>();    

public static int C(int n, int k) {
  String cacheKey=key(n,k);
  if (cache.containsKey(cacheKey){
    return cache.get(cacheKey);
  if(k>n)
    return 0;
  else if(k==0 || k==n)
    return 1;
  else {
    int result = C(n-1, k-1)+C(n-1, k);
    cache.put(cacheKey, result);
    return result ;
}

public String key(int n, int k){
  return n +"_"+k;
}

Of course using strings as keys is not the most efficient way, but I'd guess it's still way faster than recalculating the same value over and over again.

One solution would be to rebuild Pascal's triangle from the top each time, using loops instead of recursion. You will probably be performing some additions you don't need. I'm not sure how many. It would be an interesting exercise to figure out how many C(i,j) you'd be computing that your recursive function doesn't need. I'm guessing that no more than half of the computed values would be unnecessary, on average, so it should still be faster than a recursive method that recomputes the same values repeatedly, and it might be faster than using a hash table, which carries its own overhead.

You should be able to compute each row "in place" without allocating a new array for each row, to make it as efficient as possible. Say you're computing C(12,3) ; the 13th row of the triangle will have 13 elements, so you can allocate an array of length 13 to start with, and use the first N elements of the array when computing the Nth row. Say you've computed the 5th row, so the array will be

[1, 4, 6, 4, 1, x, x, ...]  // don't care about the x's

The algorithm to compute the next row would work something like this:

  • Save 1 in a temporary variable.
  • Save 4 in a temporary variable, and replace 4 with 4 + 1 (the previous value of the temporary variable).
  • Save 6 in a temporary variable, and replace 6 with 6 + 4 (the previous value of the temporary variable)
  • Save 4 in a temporary variable, and replace 4 with 4 + 6 (the previous value.... I think you can figure out how this is going to play out)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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