算法之矩阵计算斐波那契数列

本节内容

  1. 斐波那契介绍
  2. 普通方式求解斐波那契
  3. 矩阵概念
  4. 矩阵求幂
  5. 矩阵求解斐波那契

1.斐波那契介绍

斐波那契数列有关十分明显的特点,那是:前面相邻两项之和,构成了后一项。即f(n)=f(n-1)+f(n-2),f(0)=0,f(1)=f(2)=1,推导下去f(3)=2,f(4)=3,f(5)=5。。。。。。

2.普通方式求解斐波那契

按照上面提供的推导公式,普通方式求解斐波那契数列代码如下:

1 def normal(n):
2     a,b,c=0,1,1
3     while n:
4         a,b,c=b,c,b+c
5         n-=1
6     return a

使用上面的方式求解第n项斐波那契数列的时间复杂度为O(n),也就是说,时间复杂度随着n的增长而线性增长。

3.矩阵概念

开始,先来介绍一下矩阵的概念:在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合,最早来自于方程组的系数及常数所构成的方阵。

这里不介绍矩阵的各方面知识了,如果那样的话。。。就是一篇数学笔记了。。。这里只讲解矩阵相乘的概念。

矩阵相乘:矩阵相乘最重要的方法是一般矩阵乘积。它只有在第一个矩阵的列数(column)和第二个矩阵的行数(row)相同时才有意义。一般单指矩阵乘积时,指的便是一般矩阵乘积。一个m×n的矩阵就是m×n个数排成m行n列的一个数阵。由于它把许多数据紧凑的集中到了一起,所以有时候可以简便地表示一些复杂的模型。

设A为m*p的矩阵,B为p*n的矩阵,那么称m*n的矩阵C为矩阵A与B的乘积,记作C=AB:

4.矩阵求幂

上面已经介绍过了矩阵相乘的概念了,那么,斐波那契该怎么由矩阵标示呢?

从第三项开始,每一项都是前两项之和。 F(n)=F(n−1)+F(n−2), n⩾3 把斐波那契数列中 相邻的两项F(n)和F(n−1)写成一个2×1的矩阵。

斐波那契数列用矩阵推导如下:

求F(n)等于求二阶矩阵的n - 1次方,结果取矩阵第一行第一列的元素。

问题转换为二阶矩阵的n次幂。

而计算二阶矩阵的N次幂运算,由于二阶矩阵乘法满足结合律,这样,可以快速计算二阶矩阵的n次幂运算。

假设A为一个二阶矩阵,则A的幂运算满足下面的条件:

A**6=A**3∗A**3

A**7=A**3∗A**3∗A**1=A**4*A**2*A**1

在这里,我们可以类似地把A看做是二进制中的2,2**7=2**4*2**2*2**1也就是说可以把矩阵的幂转换成二进制来表示。从而可以将n次幂拆解成长度为logn的二进制数来表示:7=111(二进制)。

这就是快速求二阶矩阵的核心方法。

5. 矩阵求解斐波那契

前戏做足了,下面就该秀代码了。

 1 def multi(a,b):  # 计算二阶矩阵的相乘
 2     c=[[0,0],[0,0]]  # 定义一个空的二阶矩阵
 3     for i in range(2):
 4         for j in range(2):
 5             for k in range(2):  # 新二阶矩阵的值计算
 6                 c[i][j]=c[i][j]+a[i][k]*b[k][j]
 7     return c
 8
 9
10 def matrix(n):
11     base=[[1,1],[1,0]]  # 元矩阵,这里可以把元矩阵看做是2**0=1
12     ans=[[1,0],[0,1]]  # 结果矩阵  最开始的结果矩阵也可以看做是1,因为这个矩阵和任意二阶A矩阵相乘结果都是A
13     while n:
14         if n&1:  # 取n的二进制的最后一位和1做与运算,如果最后一位是1,则进入if体内部
15             ans=multi(ans,base)  # 如果在该位置n的二进制为1,则计算ans和base矩阵
16         base=multi(base,base)  # base矩阵相乘,相当于初始base矩阵的幂*2
17         n>>=1  # n的二进制往右移一位
18     return ans[0][1]  # 最后获取到的二阶矩阵的[0][1]即f(n)的值

最后把例子的完整代码贴出来:

 1 import time
 2
 3
 4 def multi(a,b):
 5     c=[[0,0],[0,0]]
 6     for i in range(2):
 7         for j in range(2):
 8             for k in range(2):
 9                 c[i][j]=c[i][j]+a[i][k]*b[k][j]
10     return c
11
12
13 def matrix(n):
14     base=[[1,1],[1,0]]
15     ans=[[1,0],[0,1]]
16     while n:
17         if n&1:
18             ans=multi(ans,base)
19         base=multi(base,base)
20         n>>=1
21     # for i in range(2):
22     #     print(ans[i])
23     return ans[0][1]
24
25 def normal(n):
26     a,b,c=0,1,1
27     while n:
28         a,b,c=b,c,b+c
29         n-=1
30     return a
31
32 n=int(input(">>>"))
33 start=time.time()
34 print("Normal:",normal(n))
35 print("use:",time.time()-start)
36 start=time.time()
37 print("Matrix:",matrix(n))
38 print("use:",time.time()-start)
39 #计算结果
40 >>>65536
41 Normal: 731992144602......
42 use: 0.07219505310058594
43 Matrix: 731992144602......
44 use: 0.023076772689819336

可以看出来当n的值越来越大的时候,两种方式计算出结果的时间差距将越来越大,正常的计算时间复杂度是O(n),矩阵求值的时间复杂度是O(logn)。

后记:

由此可以看出,使用推导式f(n)=f(n-1)+f(n-2)求斐波那契的第n项的算法复杂度极限为O(n),这是一维世界下的极限。将其从一维上升到二维,用二阶矩阵推导斐波那契数列时,计算的算法复杂度为O(logn),也就是说,使用升维的手段将一维空间进行扭曲从而将距离缩短,可以更快的计算出结果。

由此推导出如果人来要突破光速的极限,需要将现有的三维空间升级到四维空间,扭曲空间从而缩短距离,达到突破光速的目的。

转载于:https://www.cnblogs.com/huxianglin/p/5995649.html

算法之矩阵计算斐波那契数列相关推荐

  1. 算法 | 详解斐波那契数列问题

    14天阅读挑战赛 本篇是学习了<趣学算法(第2版)> 第一章之后总结的. 上一篇讲到了等比数列求和问题,求Sn=1+2+22+23+...+263=?S_n = 1 + 2 + 2^2 + ...

  2. 【js算法】js斐波那契数列的多种算法

    斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为"兔子数列" ...

  3. 【使用递归玩通关汉诺塔游戏】算法01-递归(斐波那契数列、汉罗塔问题)-java实现

    递归 定义:在一个方法(函数)的内部调用该方法(函数)本身的编程方式 简而言之就是 "自己调自己" 在玩游戏之前让我们先对递归有一个简单的了解吧! 5.1 递归简介 递归必须有一个 ...

  4. 【算法编程】斐波那契数列

    题目来源:牛客网剑指offer 题目描述:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项.n<=39 C++:5ms 476k #include <iostr ...

  5. 递归、尾递归、迭代算法【在 斐波拉契数列】上的实现

    /*     递归: [逆序]从未知点推到已知点,[顺序]代入已知点结果,从已知点带入并计算到未知点,最终到终点     尾递归: 从起点开始,依顺序计算结果,并无限靠近最终目标点     迭代: 从 ...

  6. 算法—递归生成斐波那契数列

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.递归生成斐波那契数列 二.使用步骤 1.伪代码 2.c 总结 前言 提示:这里可以添加本文要记录的大概内容: 例如 ...

  7. c语言斐波那契数列_神奇的数列——斐波那契数列

    斐波那契数列之美 斐波那契是一位数学家,生于公元1170年,籍贯大概是比萨,卒于1240年后.1202年,他撰写了<珠算原理>(Liber Abaci)一书.他是第一个研究了印度和阿拉伯数 ...

  8. 数据结构与算法--再谈递归与循环(斐波那契数列)

    再谈递归与循环 在某些算法中,可能需要重复计算相同的问题,通常我们可以选择用递归或者循环两种方法.递归是一个函数内部的调用这个函数自身.循环则是通过设置计算的初始值以及终止条件,在一个范围内重复运算. ...

  9. 求解斐波那契数列(Fibonacci Numbers)算法居然有9种,你知道哪几种吗?

    By LongLuo 斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多·斐波那契(Leonardoda Fibonacci)以兔子繁殖为例子而引入,故又称为&q ...

最新文章

  1. Spark shuffle调优
  2. c语言中常用的程序,C语言一些常用语句
  3. 你真的会停止线程吗?
  4. 2019长安大学ACM校赛网络同步赛 L XOR (规律,数位DP)
  5. kettle-实现每个分组的前N的数据
  6. python交通流预测代码_使用ARIMA模型进行的短时交通流预测和结果分析
  7. 常见条码及其相关概念简介
  8. [体验编译原理]编写简易计算器
  9. python 双色球 大乐透 5注随机选号
  10. 偶遇的webshell,那得冲一波
  11. Java 参数类型后面三个点,可变参数列表
  12. 解决微信设置字体大小对 rem 适配方式的影响
  13. 测试自己移动速度的软件,鼠标灵敏度测试检测工具 测试鼠标的灵敏度与移动速度...
  14. JS仿写刮刮乐小例子
  15. 在《2000年通则》中,根据卖方承担义务的不同,将13种贸易术语划分为下列四组:...
  16. python模块总结_Python常用模块资料总结和归纳
  17. ssh开启图形界面_分享|3 个 Linux 上的 SSH 图形界面工具
  18. POI导出excel,按照父子节点进行分级显示
  19. 设置WIN 7 截图工具的快捷方式
  20. OPENCV2.4.9配置

热门文章

  1. python class类里给列表排序_python笔记:Class(类)
  2. How to ignore files and directories in subversion?
  3. BZOJ1834 [ZJOI2010]network 网络扩容
  4. Unity手游之路四3d旋转-四元数,欧拉角和变幻矩阵
  5. Javascript中正则表达式的全局匹配模式
  6. 洛杉矶手机资费9.9美元包打一年
  7. phpweb2.0 开发实战 ----- 配置虚拟主机
  8. 一些奇妙的线段树操作
  9. 【集合工具类:Collections】
  10. [HAOI2008]移动玩具