斐波那契數列優化算法

最近看到斐波那契數列的算法,以爲挺簡單的,因而深刻研究了一下,發現算法其實還挺美妙的。
正常的fibonacci通常是這麼算的:算法

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

可是我在測試的時候發現,當n數值比較小的時候,這個函數性能還能夠,運行時間也不慢,可是當n取30,40,60的時候,我電腦的CPU就淡定不了,這事我發現,它們所消耗的時間以下:數組

image.png

當計算到60的時候,耗費的時間爲87.049s,不只時間太長,並且增長了CPU的壓力,感受這個算法性能不是很好。這個算法的缺點就是會重複計算許屢次相同的f(n),好比要計算f(5),將會計算兩次f(3),一次f(4),要是n取值更大的話,這些數值將會重複計算屢次,因而想減小重複計算。函數

優化方法一:利用數組標記計算過的f(n)

該方法的思路是定義一個長度爲n的數組,n的每一項初始值爲-1,當計算出每個f(n)的值時保存爲a[n],這樣下一次計算f(n)的時候,先從數組a中查看是否存在a[n]===-1,若arr[n] ===-1,則計算f(n),反之,則取a[n]的值。代碼以下:性能

function fibonacci1(n) {
  var vArray = new Array(n+1);
   for(var index = 0;index <=n;index++){
        vArray[index] = -1;
    }
  return calcFn(n,vArray)
}
function calcFn(n,arr) {
    if (n === 1 || n === 2) {
      return 1;
    }
    if(arr[n] ===-1){
      // console.log(n)
      arr[n] = calcFn((n - 1),arr) + calcFn((n - 2),arr)
    }
    return arr[n]
}

計算結果:如下分別是n爲30,40,60的計算結果測試

image.png

從上圖來看,相對於第一種通用的方式,這個方法計算較大數值時,耗時明顯縮短了,大大提升了運算速度。優化

優化方法二:a[n]=a[n-1]+a[n-2]

該方法的思路是,根據此通項的計算原理,a[n]=a[n-1]+a[n-2],咱們只須要保留a[n]的前兩項,由f(1)=f(2)=1可知,咱們可初始化一個長度爲2的數組a=[1,1],則f(3)=a[0]+a[1]=3,而後可將交換移動數組的的兩項,好比計算完f(3)以後,a=[1,3],此時的數組a表明a[0] = f(2),a[1]=f(3),若我要計算f(4),則f(4)=a[0]+a[1],以此類推。代碼以下:spa

function fibonacci2(n) {
  var arr = [1, 1];
  for(let i = 3; i <= n; ++i) {
      let temp = arr[1]
      arr[1] += arr[0]
      arr[0] = temp
  }
  return arr[1]
}

實驗結果代表,此方法優化以後,計算耗時跟優化方法一差很少code

總結

兩種優化的方法都能縮短計算耗時,均可以免同一數值屢次計算,二者的差別:blog

  • 方法一更容易理解,但代碼不夠簡潔
  • 方法二代碼簡潔,思路比較靈活
  • 方法一須要定義一個長度跟n同樣的數組,缺點是若n比較大,那這個數組的長度也會很大,且會保留每一項
  • 方法二隻須要保留n-1,n-2兩項,無論n爲多大,只須要定義長度爲2的數組,就可實現
相關文章
相關標籤/搜索