memoization提高遞歸效率

從開通博客到目前爲止,也有一年了,剛開始的寫了一篇工做的感想,而後就一直不知道寫什麼,看園子裏的文章實在是很專業,怕本身寫的太水。可是,寫一些東西總歸是好的,因而就看成是記筆記同樣,開始寫第一篇技術類的文章。javascript

最近打算鞏固增強javascript知識,因此開始作codewars, 經過解決codewars的kata,真的瞭解了一些沒有注意的知識點。最近就瞭解了一下,之前沒有聽過的memoization.java

codewars的題目是這樣寫的:數組

給一個整數n,寫一個函數返回fibonacci數列的第n個數,而且不但願執行函數後還要去泡杯咖啡來等待結果~囧~,而後提出了'implement the memoization solution'。因爲以前沒有據說過memoization,因此就去google了一下了解到底什麼是memoization。緩存

 

一  memoization簡介
函數

 

維基百科是這樣描述的:優化

memoization最初是用來優化計算機程序使之計算的更快的技術,是經過存儲調用函數的結果而且在一樣參數傳進來的時候返回結果。大部分應該是在遞歸函數中使用。google

memoization這個詞是在1968年被Donald Michie創造出來的,它源於拉丁語memoradum,在英語中一般簡寫爲memo,所以就有了將一個函數的返回結果暫存入某個變量中的意思。(翻譯水平略渣,若有不對,歡迎指正拍磚)。spa

 

二  經過Fibonacci例子進一步瞭解翻譯

 

通常實現輸出fibonacci數列第n個數,應該使用遞歸調用,代碼是這樣的:code

function fibonacci(n){
   if(n==0||n==1){
        return n;
    }
    return fibonacci(n-1) + fibonacci(n-1);
}        

因爲遞歸函數會重複調用不少遍函數,傳入一樣的參數,獲得一樣的結果,實際是重複實現同一個行爲,就會致使效率很低。好比執行fibonacci(5),就要先算出fibonacci(4)和fibonacci(3);而計算fibonacci(4)和fibonacci(3),就要計算fibonacci(3),fibonacci(2)和fibonacci(2),fibonacci(1),這就像一個樹同樣,每一個分支都要重複計算,直到獲得fibonacci(1)爲止。以下圖所示: 

 

這樣就會致使須要計算不少遍的重複數據,因而想到是否可以把已經計算過的結果暫時存起來,等到下次用的時候直接取出結果。因此定義了一個數組用來存放計算過的數據,而後在須要的時候從數組中查詢,這樣就會省去不須要的計算,提升程序的效率。代碼以下:

var fibonacci = (function(){
  var cache = [];           //定義一個空的存放緩存的數組
  return function(n){      
    if(n === 0 || n === 1){
      return n;
    }else{
      cache[n-1] = cache[n-1]||fibonacci(n-1); //先從cache數組裏查詢結果,若是沒找到的話在計算
      cache[n-2] = cache[n-2]||fibonacci(n-2);
      return cache[n-1]+cache[n-2];
    }
  }
})();

三 總結

memorization 能夠把函數每次的返回值存在一個數組或者對象中,在接下來的計算中能夠直接讀取已經計算過而且返回的數據,不用重複屢次相同的計算。這種方法可用於部分遞歸中以提升遞歸的效率。

最後,本文若是有任何有問題的地方,歡迎批評指正。

相關文章
相關標籤/搜索