兔子問題:已知一對兔子每一個月可以生一對小兔子,而一對兔子出生後.第三個月開始生小兔子,假如沒有發生死亡,則每個月有多少兔子?
#按照兔子的對數進行考慮,完全是一個斐波拉契數列
#方法一:遞歸調用,每次遞歸的時候有大量重複計算,效率低,可將其調用的過程轉化成一顆二叉樹進行分析,
# 二叉樹的總結點個數不超過(2^n-1)個,由於其是不完全二叉樹,那麼函數計算的次數必小於(2^n-1),
# 時間複雜度爲O(2^n);遞歸調用的深度爲n,空間複雜度爲O(n)
def rabbit(month):
return 1 if (month<3) else (rabbit(month - 1) + rabbit(month - 2))
if __name__ == '__main__':
month=int(input('輸入月數:'))
print('兔子每個月的數量變化:')
for i in range(1,month+1):
print(2*rabbit(i),end='\t')
#方法二:非遞歸循環方式,將前兩項的計算結果保存起來,無重複計算,時間複雜度爲O(n),空間複雜度爲O(1)
def rabbit(month):
i,j=0,1
while i<month+2:
if i>0:
print(2 * i)
i,j=j,i+j
if __name__ == '__main__':
month=int(input('輸入月數:'))
print('兔子每個月的數量變化:')
rabbit(month)
#方法三:直接利用數學公式法:f(n)={[(1+5^0.5)/2]^n - [(1-5^0.5)/2]^n}/(5^0.5),
# 時間複雜度爲O(1),空間複雜度爲O(1)
import math
def rabbit(n):
return (pow((1 + math.sqrt(5.0)) / 2, n) - pow((1 - math.sqrt(5.0)) / 2, n)) / math.sqrt(5.0)
if __name__ == '__main__':
month=int(input('輸入月數:'))
print('兔子每個月的數量變化:')
for i in range(1,month+1):
print(2*int(rabbit(i)),end='\t')
#方法四:矩陣的乘法,時間複雜度僅爲O(log n),空間複雜度爲O(1),時間效率雖然低,但不夠實用,源碼太過繁瑣
import copy
def rabbit(month):
M = [[1, 1], [1, 0]]
N = [[1, 1], [1, 0]]
P = [[1, 1], [1, 0]]
while month<=2 and month>0:
print(2*P[0][0],end='\t')
month-=1
if month>2:
print(2 * P[0][0], end='\t')
print(2 * P[0][0], end='\t')
while month > 2:
# P[0][0] = M[0][0] * N[0][0] + M[0][1] * N[1][0]
# P[0][1] = M[0][0] * N[0][1] + M[0][1] * N[1][1]
# P[1][0] = M[1][0] * N[0][0] + M[1][1] * N[1][0]
# P[1][1] = M[1][0] * N[0][1] + M[1][1] * N[1][1]
for i in range(2): # i 可以取0 1; P的 0 1 行
for j in range(2): # j ,P的0 1 列
# 參與的總是:M的i行,N的j列
if i == 0:
P[i][j] = M[0][0] * N[0][j] + M[0][1] * N[1][j]
if i == 1:
P[i][j] = M[1][0] * N[0][j] + M[1][1] * N[1][j]
print(2*P[0][0],end='\t')
M=copy.deepcopy(P)
month -= 1
if __name__ == '__main__':
month=int(input('輸入月數:'))
print('兔子每個月的數量變化:')
rabbit(month)
方法四的公式如下:
f(n) f(n-1) 1 1
[ ] = [ ]^(n-1)
f(n-1) f(n-2) 1 0
運行結果:
輸入月數:6
兔子每個月的數量變化:
2 2 4 6 10 16