简体   繁体   English

二项式系数。 递归树。 如何避免多次计算相同的值

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

I am working with my program called BinomialCoefficients .我正在使用名为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.我在C(5,3)上做了一个盒子跟踪,它返回10这是正确的,但我注意到在C(5, 3)完整递归树中,值C(3, 2)被评估了 2 次,并且C(2, 1)被评估 3 次。

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)但是你必须考虑整数溢出......(编辑:看看@ajb在评论中说了什么)

I'd suggest using a Map for caching result:我建议使用 Map 来缓存结果:

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.计算出您要计算的递归函数不需要多少C(i,j)将是一个有趣的练习。 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) ;假设您正在计算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.三角形的第 13 行将有 13 个元素,因此您可以分配一个长度为 13 的数组开始,并在计算第 N 行时使用数组的前N元素。 Say you've computed the 5th row, so the array will be假设你已经计算了第 5 行,所以数组将是

[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.将 1 保存在临时变量中。
  • Save 4 in a temporary variable, and replace 4 with 4 + 1 (the previous value of the temporary variable).将 4 保存在临时变量中,并将 4 替换为 4 + 1(临时变量的先前值)。
  • Save 6 in a temporary variable, and replace 6 with 6 + 4 (the previous value of the temporary variable)将6存入一个临时变量中,将6替换为6+4(临时变量之前的值)
  • 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)将 4 保存在一个临时变量中,并将 4 替换为 4 + 6(之前的值......我想你可以弄清楚这是怎么回事)

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

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