簡體   English   中英

二項式系數。 遞歸樹。 如何避免多次計算相同的值

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

我正在使用名為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);
  }

一種修改是使用乘法公式 但是你必須考慮整數溢出......(編輯:看看@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;
}

當然,使用字符串作為鍵並不是最有效的方法,但我猜它仍然比一遍又一遍地重新計算相同的值要快得多。

一種解決方案是每次從頂部重建帕斯卡三角形,使用循環而不是遞歸。 您可能會執行一些不需要的添加。 我不確定有多少。 計算出您要計算的遞歸函數不需要多少C(i,j)將是一個有趣的練習。 我猜測平均而言,不超過一半的計算值是不必要的,因此它仍然應該比重復重新計算相同值的遞歸方法更快,並且它可能比使用哈希表更快,它攜帶它自己的開銷。

您應該能夠“就地”計算每一行,而無需為每一行分配一個新數組,以使其盡可能高效。 假設您正在計算C(12,3) 三角形的第 13 行將有 13 個元素,因此您可以分配一個長度為 13 的數組開始,並在計算第 N 行時使用數組的前N元素。 假設你已經計算了第 5 行,所以數組將是

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

計算下一行的算法的工作原理如下:

  • 將 1 保存在臨時變量中。
  • 將 4 保存在臨時變量中,並將 4 替換為 4 + 1(臨時變量的先前值)。
  • 將6存入一個臨時變量中,將6替換為6+4(臨時變量之前的值)
  • 將 4 保存在一個臨時變量中,並將 4 替換為 4 + 6(之前的值......我想你可以弄清楚這是怎么回事)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM