費波納數列:
n=0, f(0)=0;
n=1,f(1)=1;
n>1, f(n)=f(n-1)+f(n-2)
這裡面一定要注意的是n >= 0, 所以需要判斷若n < 0 ,則直接return none.
處理辦法:
第一種很自然的想到遞迴:
def fibonacci(n):
#其實沒必要關心n<0,因為此處測試例項這裡沒有n<0的測試例子
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1)+fibonacci(n-2)
通過遞迴的基本知識我們知道其時間複雜度是2的n次方,由於函式內部2次呼叫遞迴,故每次二分,所以時間複雜度是2的n次方,所以這是非常不能接受的。舉例:當n等於100的時候,執行次數是1024的10次方,這是乙個天文資料,所以不合適,一般的直接遞迴的方法處理資料往往不是太可行。
第二種:直接遞迴的基礎上加上functools裡面的lru_catch這個裝飾器熟悉lru_catch原理的都知道,它的底層實現是字典,字典的底層實現是hashmap,所以字典查詢的時間複雜度是1,在該數列中,我們可以發現後面的呼叫相比前面有較大的資料重複,所以如果採用此裝飾器將前面的資料儲存起來,每次相同的資料那麼只執行一次,所以時間複雜度就是n,直接大大下降。
這部分如果自己實現,那麼可以每次儲存,遞迴前檢查這個字典,這是自己實現的原理。
不自己實現就是用人家自己實現好的裝飾器,**如下:
from functools import lru_cache
@lru_cache()
def fibonacci(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fibonacci(n-1)+fibonacci(n-2)
第三種就是最直接的用迴圈代替遞迴
def fibonacci(n):
fi = [0 ,1]
if n == 0:
return 0
elif n == 1:
return 1
else:
for i in range(2, n):
return fi[-1]
這就是該題目的解法,時間複雜度未o(n)。
下面詳細**對於遞迴的理解、自己直觀的寫遞迴函式、以及遞迴函式的一般優化手段
遞迴的理解
自己如何寫遞迴函式
遞迴的優化
如何確定乙個問題不是使用遞迴演算法一般而言,這個問題如果能被分解 為乙個遞推式和邊界判斷,那麼此時該問題就能用遞迴來表達,但是如何才能確定該問題能寫為乙個遞推式呢?一般而言,能用遞迴的都是問題 該問題分解形狀都是類似於 幾叉數,後面的解依賴於前面的解,所以一般問題如果有此形式的話,那麼可以考慮使用遞迴演算法。
先將問題逆向考慮,因為要寫遞推式從n開始發現n-1、n-2、n-等等的關係,所以要逆向考慮,看執行該行文正向和逆向過程是否一樣。
比如青蛙跳台,正著跳和逆著跳結果是一致的,所以滿足此步。
確定該問題是否適合用遞迴 問題可能幾叉分解、依賴於前面的結果,考慮使用遞迴即其迴圈優化、裝飾器優化
使用遞迴演算法的第一步就是寫出 邊界條件和遞迴表示式,這一點要切記。
當寫出遞推式以後 進行遞推式化解,盡可能簡單
此時可以直接遞迴,也可以迴圈處理了,遞迴表示式本身就是一種迴圈,依賴於前面的結果麼,所以迴圈往後面計算處理即可。
基於遞迴的斐波那契數列的兩個題目青蛙跳台階:分析。青蛙跳台階按照上述步驟處理,本質上就是乙個費波納且數列。
class solution:
def jumpfloor(self, n):
fi = [1, 2]
if n >= 0 and n <= 2:
return n
elif n < 0 :
return none
else:
for i in range(2, n):
return fi[-1]
青蛙**跳台階: 當然寫出遞推式,發現就是f(n)=f(n-1)+f(n-1)+f(n-2)+...f(2)+f(1)+1,所以迴圈最後一項就是前面所有項的和,這樣的問題肯定不能用遞迴處理了,那麼智慧型迴圈處理了。
class solution:
def jumpfloorii(self, number):
# write code here
taijie = [0, 1]
if number < 0:
return none
elif number >=0 and number <=1:
return taijie[number]
else:
for i in range(2, number+1):
return taijie[-1]
但是可以發現,f(n-1)=f(n-2)+...f(2)+f(1)+1,所以上述的f(n)=2f(n-1),直接簡化了迴圈條件,所以這是對於遞迴問題的簡化以及遞迴條件的變形,人人呢屬於上述範疇。 《劍指Offer》斐波納契數列
描述 查詢斐波納契數列中第 n 個數。所謂的斐波納契數列是指 斐波納契數列的前10個數字是 0,1,1,2,3,5,8,13,21,34 樣例 給定 1,返回 0 給定 2,返回 1 給定 10,返回 34 解答解析 這道題可以使用遞迴來解答,但是遞迴所消耗的時間複雜度與空間複雜度都比較大,因此我們...
PHP實現費波納奇數列
迴圈制 初始化前兩個引數為1,其中定義陣列來做的原因是方便理解 迴圈開始,以下標為2開始處理 不斷往陣列中新增,當前迴圈次數的下表對應的值是前兩個值得和 array array array 0 1 array 1 1 for i 2 i 10 i print r array 遞迴處理 定義結束遞迴的...
劍指offer 斐波那契數列
題目1描述 寫乙個函式,輸入n,求斐波那契數列的第n項。斐波那契數列的定義如下 f n 0 n 0 f n 1 n 1 f n f n 1 f n 2 n 1 分析描述 在大多數的c語言教科書中,一般會用遞迴求斐波那契數列。如下 long long fibonacci unsigned int n ...