斐波那契數列(二)--矩陣優化演算法
阿新 • • 發佈:2018-12-24
之前寫了一篇從斐波那契數列分析遞迴與動態規劃(JAVA)來優化斐波那契數列,這樣可以使演算法的時間複雜度從O(n^2)變到O(n),這是使用遞迴公式f(n)=f(n-1)+f(n-2)求斐波那契數列的最優演算法,但是這只是一維世界下的極限。下面我們將其從一維上升到二維,用二階矩陣推導斐波那契數列,該演算法的複雜度為O(logn)。
矩陣定義
一個m*n的矩陣是一個由m行n列元素排成的矩形陣列。矩陣裡的元素可以是數字符號或者數學式.
下面是一個典型的二階矩陣
二階矩陣的乘法
高效冪運算
第一種方法在高效冪運算(JAVA)中有類似的描述,雖然本文中是對矩陣進行冪運算,實質是一樣的
第二種方法利用位運算轉換成二進位制處理
斐波那契數列的矩陣演算法
import java.util.Scanner; /** * [F(n+1) F(n)] [1 1 ]^n | | =| | [F(n) F(n-1)] [1 0 ] * */ public class Main { // 公式矩陣 private static final int[][] UNIT = {{1, 1}, {1, 0}}; // 零矩陣 private static final int[][] ZERO = {{0, 0}, {0, 0}}; public static void main(String[] args) { Scanner in = new Scanner(System.in); int n = in.nextInt(); int[][] m = fb(n); System.out.println(m[0][1]); } /** * 利用二進位制進行高效冪運算 * 求斐波那契數列 * */ public static int[][] fb(int n) { if (n == 0) { return ZERO; } if (n == 1) { return UNIT; } if (n%2 == 0) { System.out.println(n >> 1); int[][] matrix = fb(n >> 1); return Multiply(matrix, matrix); } else { int[][] matrix = fb((n - 1) >> 1); return Multiply(Multiply(matrix, matrix), UNIT); } } /** * 矩陣乘法 * */ public static int[][] Multiply(int[][] m, int[][] n) { /** * 對於斐波那契數列來說,行和列都是2,這樣寫更易於理解,下面也給出了標準的矩陣乘法演算法,是通用的 * 用到此演算法,除非進行演算法學習和研究,否則一般都是進行較大資料的斐波那契求值,所以對結果取(10e9)+7的模 * */ int[][] r = new int[2][2]; r[0][0] = (m[0][0]*n[0][0] + m[0][1]*n[1][0])%1000000007; r[0][1] = (m[0][0]*n[0][1] + m[0][1]*n[1][1])%1000000007; r[1][0] = (m[1][0]*n[0][0] + m[1][1]*n[1][0])%1000000007; r[1][1] = (m[1][0]*n[0][1] + m[1][1]*n[1][1])%1000000007; return r; } }
標準矩陣乘法演算法:
public static int[][] Multiply(int[][] m, int[][] n) { // 標準計算矩陣乘法演算法 int rows = m.length; int cols = n[0].length; int[][] r = new int[rows][cols]; for (int i = 0; i < rows; i++) { for (int j = 0; j < cols; j++) { r[i][j] = 0; for (int k = 0; k < m[i].length; k++) { r[i][j] += m[i][k] * n[k][j]; } } } return r; } }