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

时间:2016-04-19 04:40:29

标签: java recursion tree binomial-coefficients

我正在处理名为 BinomialCoefficients 的程序。

我在C(5,3)上做了一个方框跟踪并返回10这是正确的,但我注意到在C(5, 3)的完整递归树中,值C(3, 2)是评估2次,C(2, 1)评估3次。

什么可以修改,以避免多次计算相同的值?

这里只是显示上下文的功能。

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

2 个答案:

答案 0 :(得分:1)

一个修改是使用multiplicative formula。但你必须考虑整数溢出.... (编辑:看一下@ ajb 在评论中说的内容)

我建议使用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;
}

当然使用字符串作为键并不是最有效的方法,但我猜它仍然比一遍又一遍地重新计算相同的值更快。

答案 1 :(得分:0)

一种解决方案是每次从顶部重建Pascal的三角形,使用循环而不是递归。你可能会执行一些你不需要的补充。我不知道有多少。这将是一个有趣的练习,可以计算出你的递归函数不需要计算的C(i,j)C(12,3)。我猜测平均不超过一半的计算值是不必要的,所以它应该比重复计算相同值的递归方法更快,并且它可能比使用哈希表更快它自己的开销。

您应该能够“就地”计算每一行,而无需为每一行分配新数组,以使其尽可能高效。假设你正在计算N;三角形的第13行将有13个元素,因此您可以分配一个长度为13的数组,并在计算第N行时使用数组的第一个[1, 4, 6, 4, 1, x, x, ...] // don't care about the x's 元素。假设你计算了第5行,那么数组将是

  <div class="main-div">
<div class="myBox"></div> <!--This red rectangle is the header. The scrollable content should not overlap with this.-->
<div class="scrollable-content horizontal">
    <ul>
        <li>First Item</li>
        <li>Second Item</li>
        <li>Third Item</li>
        <li>Fourth Item</li>
        <li>Fifth Item</li>
        <li>Sixth Item</li>
        <li>Seventh Item</li>
        <li>Eight Item</li>
        <li>Ninth Item</li>
        <li>Tenth Item</li>
        <li>First Item</li>
        <li>Second Item</li>
        <li>Third Item</li>
        <li>Fourth Item</li>
        <li>Fifth Item</li>
        <li>Sixth Item</li>
        <li>Seventh Item</li>
        <li>Eight Item</li>
        <li>Ninth Item</li>
        <li>Tenth Item</li>
        <li>First Item</li>
        <li>Second Item</li>
        <li>Third Item</li>
        <li>Fourth Item</li>
        <li>Fifth Item</li>
        <li>Sixth Item</li>
        <li>Seventh Item</li>
        <li>Eight Item</li>
        <li>Ninth Item</li>
        <li>Tenth Item</li>
        <li>First Item</li>
        <li>Second Item</li>
        <li>Third Item</li>
        <li>Fourth Item</li>
        <li>Fifth Item</li>
        <li>Sixth Item</li>
        <li>Seventh Item</li>
        <li>Eight Item</li>
        <li>Ninth Item</li>
        <li>Tenth Item</li>
    </ul>  

计算下一行的算法可以这样工作:

  • 将1保存在临时变量中。
  • 将4保存在临时变量中,并将4替换为4 + 1(临时变量的先前值)。
  • 将6保存在临时变量中,并将6替换为6 + 4(临时变量的先前值)
  • 在一个临时变量中保存4,并将4替换为4 + 6(之前的值......我想你可以弄清楚这是怎么发生的)