[演算法題目] Nth Fibonacci

本題資訊

難度:easy
使用語言:C++
相關概念:Recursion


題目敘述

Write a function that takes in an integer n and returns the nth Fibonacci number.

首先介紹一下 Fibonacci (費波納契)數列的定義:

\(\begin{cases}
F_0 = 0, F_1 = 1 \\
F_n = F_{n-1} + F_{n-2} & \text{ when } n \geq 2
\end{cases}\)

費氏數列最初由 0, 1 兩個數字開始,並且每個數字是前面兩數相加而得出。

Idea 1

可以直接從定義出發,每次回傳的值都是前兩個數相加,前兩個數怎麼來的呢?分別是所在位置的前兩個數相加……如此重複下去。

using namespace std;

int getNthFib(int n) {
  if (n == 1) {
    return 0;
  } else if (n == 2) {
    return 1;
  } else {
    return getNthFib(n - 1) + getNthFib(n - 2);
  }
}

時間複雜度:\(O(2^n)\),\(n\) 代表 input 的數字。
空間複雜度:\(O(1)\)

Idea 2

仔細想想,Fibonacci 數列中每個數字生成也只需要數列中最後兩個數字,可以只用兩格完成(依定義我只需要前兩個數字即可)。

作法 1

創一個 tmp = {0, 1} 表示數列最開頭的兩個數字,並且設定一個計數器從3開始算。執行一個迴圈,若計數器小於目前的 n,則重複以下步驟:
設定 nexttmp 裡面兩個數字(也就是目前數列最後兩個數字)相加,得出目前的 Fibonacci 數並存在 tmp 的第 2 格,tmp 的第 1 格則存放先前在第 2 格的數字。

using namespace std;

int getNthFib(int n) {
  int tmp[] = {0, 1};
  int counter = 3;

  while(counter <= n){
    int next = tmp[0] + tmp[1];
    tmp[0] = tmp[1];
    tmp[1] = next;
    counter++;
  }
  return n > 1 ? tmp[1] : tmp[0];
}

作法 2

這個作法 2 和作法 1 的想法類似,只是作法稍微不同。首先也是創一個 tmp = {0, 1} 表示數列最開頭的兩個數字,但我們不用多設定一個空間 next 了,直接利用 n 和 2 相除的餘數(只會有 0 和 1)當成要改變的 index 即可,算是一種沒那麼直覺的小技巧。

using namespace std;

int getNthFib(int n) {
  int tmp[] = {0, 1};
  for (int i=2; i<n; i++){
    tmp[i%2] += tmp[(i+1) % 2];
  }
  return tmp[(n-1) % 2];
}

時間複雜度:\(O(n)\),\(n\) 代表 input 的數字。
空間複雜度:\(O(1)\)

讓我知道你在想什麼!