每日分享
The great pleasure in life is doing what people say you cannot do.
人生最大的快乐就是做到别人认为你做不到的事情。
小闫语录:
当我们鼓起勇气去做一件事情的时候,耳边总是会有这么一个声音『你不适合做。/你肯定不行的。/你做梦呢吧?......』各种各样类似的打击。它们让我们丧失信心,甚至怀疑自己。你要明白,这个世界上最懂你的人,不是朋友,不是亲戚,是你自己!你自己最有发言权。如果认定,请坚持。你要做的,就是做到他们认为你做不到的事情,不是为了向他们证明自己,而是告诉自己『我的人生我做主,我说行,不行也行!』
python实现斐波那契数列的多种方式
斐波那契数列
1,1,2,3,5,8,13,21,34,55,89,144,233,377.....这个数列就是大名鼎鼎的斐波那契数列。它被称为黄金分割数列,在面试中也没少碰到它。巴拉巴拉......假装我介绍了很多,下面直接看干货。
首先我们引入一下时间复杂度这个概念,这个是检验算法所耗时间的长短。检验代码的质量终究还是要看算法的。因为下文中我们需要用时间复杂度衡量一下各算法的效率怎么样,寻找一种最优方法。
上图代表的是大量数据的增加,函数所耗费的时间怎么样。
Element元素
operations 运算,作用
Big-O Complexity Chart 大O表示法时间复杂度图
最简单的实现
a, b= 0, 1 while b < 1000: print(b,end=',') a, b = b, a+b
这个就是我们在初学python时的一种写法,随着我们学习的深入了解,我们也用到了不同的方法实现。
函数实现
1.递推法
首先忽略我代码中无聊的注释方法,哈哈哈~~~~
############################## # 使用`递推法`实现斐波那契数列 # ############################# def fib_next(n): first_number = 0 second_number = 1 for _ in range(n): first_number, second_number = second_number, first_number+second_number return first_number if __name__ == '__main__': [print(fib_next(i),end=',') for i in range(1,15)]
据说这种方法的时间复杂度是O(n),从图表中对应查看,可以得知这种方法随着数量的增加,速度会越来越慢越来越慢,显然是不可取的。
2.递归法
############################## # 使用`递归法`实现斐波那契数列 # ############################# def fib_recursive(n): assert n >= 0, "n must be larger than 0" if n <= 1: return n return fib_recursive(n-1) + fib_recursive(n-2) if __name__ == '__main__': [print(fib_recursive(i),end=',') for i in range(1,15)]
这种写法最简单,相对来说很好理解。但是效率却相当的低......,时间复杂度是O(1.618^n)
3.生成器
############################## # 使用`生成器`实现斐波那契数列 # ############################# def fib_generator(max): first_number, second_number = 0, 1 while max > 0: first_number, second_number = second_number, first_number+second_number max -= 1 yield first_number if __name__ == '__main__': [print(i,end=',') for i in fib_generator(15)]
使用生成器的方法是一种不错的想法。但是仍然不是最好的。
4.矩阵
在看下面的两种方法之前,我们先来看一下矩阵,这是线性代数里面的一块内容。下面简单的解释一下矩阵乘法:
图中左数第一个矩阵的第一行每个元素和第二个矩阵的这一列每个元素做如下的运算:
2*1+1*0=2
得到的2作为第三个矩阵的第一行第一列的元素值。同理:
1*1+0*0=1
第三个矩阵的第二行第一列的元素值为1。因此两个矩阵相乘得到第三个矩阵。
4.1第一种方法
############################ # 使用`矩阵`实现斐波那契数列 # ########################### import numpy def fib_matrix(n): res = pow((numpy.matrix([[1, 1], [1, 0]])), n) * numpy.matrix([[1], [0]]) return res[0][0] if __name__ == '__main__': [print(int(fib_matrix(i)), end=',') for i in range(10) ]
因为幂运算可以使用二分加速,所以矩阵法的时间复杂度为 O(log n)
4.2第二种方法
########################## # 使用矩阵计算斐波那契数列 # ######################### import numpy def Fibonacci_Matrix_tool(n): Matrix = numpy.matrix("1 1;1 0") # 返回的是matrix类型 return pow(Matrix, n) def Fibonacci_Matrix(n): result_list = [] for i in range(0, n): result_list.append(numpy.array(Fibonacci_Matrix_tool(i))[0][0]) return result_list # 调用 if __name__ == '__main__': a = Fibonacci_Matrix(10) print(a)
用科学计算包numpy来实现矩阵法 O(log n)
类实现
1.类
####################################### # `类内实现内部魔法方法`实现斐波那契数列 # ###################################### class Fibonacci(object): def __init__(self, num): self.num = num def __iter__(self): if self.num < 1: return 1 first_number, second_number = 0, 1 while self.num > 0: first_number, second_number = second_number, first_number + second_number self.num -= 1 yield first_number def __next__(self): return self.__iter__() if __name__ == '__main__': f = Fibonacci(15) [print(i,end=',') for i in f]
参考文献: