题目:
计算斐波那契数列。具体什么是斐波那契数列,那就是0,1,1,2,3,5,8,13,21,34,55,89,144,233。
要求:
时间复杂度尽可能少
分析:
给出了三种方法:
方法1:递归的方法,在这里空间复杂度非常大。如果递归层数非常多的话,在python里需要调整解释器默认的递归深度。默认的递归深度是1000。我调整了半天代码也没有调整对,因为递归到1000已经让我的电脑的内存有些撑不住了。
方法2:将递归换成迭代,这样时间复杂度也在代码中标注出来了。
方法3:这种方法利用了求幂的简便性,采用了位运算。但是代价在于需要建立矩阵,进行矩阵运算。所以,当所求的数列的个数较小时,该方法还没有第二种简便。但是当取的索引值n超级大时,这种方法就非常方便了。时间复杂度在代码中标注出来了。
代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
#!usr/bin/python2.7
# -*- coding=utf8 -*-
# @Time : 18-1-3 下午2:53
# @Author : Cecil Charlie
import sys
import copy
sys.setrecursionlimit( 1000 ) # 用来调整解释器默认最大递归深度
class Fibonacci( object ):
def __init__( self ):
pass
def fibonacci1( self , n):
'''
原始的方法,时间复杂度为 o(2**n),因此代价较大
:param n: 数列的第n个索引
:return: 索引n对应的值
'''
if n < 1 :
return 0
if n = = 1 or n = = 2 :
return 1
return self .fibonacci1(n - 1 ) + self .fibonacci1(n - 2 )
@staticmethod
def fibonacci2(n):
"""
用循环替代递归,空间复杂度急剧降低,时间复杂度为o(n)
"""
if n < 1 :
return 0
if n = = 1 or n = = 2 :
return 1
res = 1
tmp1 = 0
tmp2 = 1
for _ in xrange ( 1 , n):
res = tmp1 + tmp2
tmp1 = tmp2
tmp2 = res
return res
def fibonacci3( self , n):
"""
进一步减少迭代次数,采用矩阵求幂的方法,时间复杂度为o(log n),当然了,这种方法需要额外计算矩阵,计算矩阵的时间开销没有算在内.其中还运用到了位运算。
"""
base = [[ 1 , 1 ], [ 1 , 0 ]]
if n < 1 :
return 0
if n = = 1 or n = = 2 :
return 1
res = self .__matrix_power(base, n - 2 )
return res[ 0 ][ 0 ] + res[ 1 ][ 0 ]
def __matrix_power( self , mat, n):
"""
求一个方阵的幂
"""
if len (mat) ! = len (mat[ 0 ]):
raise ValueError( "The length of m and n is different." )
if n < 0 or str ( type (n)) ! = "<type 'int'>" :
raise ValueError( "The power is unsuitable." )
product, tmp = [], []
for _ in xrange ( len (mat)):
tmp.append( 0 )
for _ in xrange ( len (mat)):
product.append(copy.deepcopy(tmp))
for _ in xrange ( len (mat)):
product[_][_] = 1
tmp = mat
while n > 0 :
if (n & 1 ) ! = 0 : # 按位与的操作,在幂数的二进制位为1时,乘到最终结果上,否则自乘
product = self .__multiply_matrix(product, tmp)
tmp = self .__multiply_matrix(tmp, tmp)
n >> = 1
return product
@staticmethod
def __multiply_matrix(mat1, mat2):
"""
矩阵计算乘积
:param m: 矩阵1,二维列表
:param n: 矩阵2
:return: 乘积
"""
if len (mat1[ 0 ]) ! = len (mat2):
raise ValueError( "Can not compute the product of mat1 and mat2." )
product, tmp = [], []
for _ in xrange ( len (mat2[ 0 ])):
tmp.append( 0 )
for _ in xrange ( len (mat1)):
product.append(copy.deepcopy(tmp))
for i in xrange ( 0 , len (mat1)):
for j in xrange ( 0 , len (mat2[ 0 ])):
for k in xrange ( 0 , len (mat1[ 0 ])):
if mat1[i][k] ! = 0 and mat2[k][j] ! = 0 :
product[i][j] + = mat1[i][k] * mat2[k][j]
return product
f = Fibonacci()
print f.fibonacci1( 23 )
print f.fibonacci2( 23 )
mat1 = [[ 2 , 4 , 5 ],[ 1 , 0 , 2 ],[ 4 , 6 , 9 ]]
mat2 = [[ 2 , 9 ],[ 1 , 0 ],[ 5 , 7 ]]
print f.fibonacci3( 23 )
|
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/dongrixinyu/article/details/78964498