分割統治のオープンクラス網易第三話の記事<アルゴリズムの紹介>。Iは分裂との新たな理解と征服するために使用し、また、金色の列としても知られているフィボナッチ数、 F0 = 0、F1 = 1、のFn = F(N - 1)+ F(N - 2)( N> = 2、n∈N*)
これらの3つのメソッドを達成するために、それぞれ今、私は、Javaを使用します(またはい、しかし、Javaのが、私はイデオロギー的に焦点を当て、まあ何の問題、アルゴリズムを考えていません)。半分参照するには、後でビデオは、作られた時間を単純な再帰法を使用してこの問題を解決するために、今では、多くの反復サブ問題があり、これは、動的プログラミングの基本的な考え方に沿ったものである、とボトムアップの順序を使用して解決することができ、サブ問題の結果を保存します。この時間を行うためのアルゴリズムは次のとおりです。シータ(N)
1.単純な再帰:ダウン解く自己監督問題、解決するために、繰り返しの多くをもたらし
2.動的計画:正確溶液からの「動的計画」ボトムアップのアイデアでなければなりません。
(さえ線形代数行列式による)3.数学的帰納
Fnは第nを設定フィボナッチ数を、そこ定理:
証明: N = 1、F0 = 0、 F1 = 1、F2 = 2、 すなわち:
だから、定理が真であると仮定すると、それは、n-1の発現に持ち込まなければならないであろう。
すなわち:
方程式ので、
恒久的施設、そして仮説。
このようなフィボナッチ数は、電源の問題に変換し、N、そしてnはアルゴリズムの時間電源の問題なぜされますが、何?分割し、n個のパワーを解く数問題を克服N左右部品(でもD場合に等しい乗法であってもよい本明細書で使用されることができるN / 2、N / 2、奇数ワード(N-1)/ 2と(N- 1)/ 2)。そこ:
Nでも簡単に分割することにより、この数回。
コードは以下の通りであります:
package com.wly.algorithmproblem;
/**
* 解斐波拉契数列问题,使用三种方法:朴素递归解法、自底向上的动态规划思想解法、线性代数矩阵连乘公式解法
* @author wly
* @date 2013-11-28
*
*/
public class FibonacciSequence {
private static int TESTCASE = 43;
private static int[][] matrixUnit = {{1,1},{1,0}};
public static void main(String[] args) {
System.out.println("测试规模:" + TESTCASE);
//---朴素递归解斐波那契数列问题测试
long startT = System.currentTimeMillis();
System.out.println("朴素递归:" + simpleRecurrence(TESTCASE));
System.out.println("朴素递归用时:" + (System.currentTimeMillis()-startT));
//---自底向上(动态规划)解斐波那契数列问题测试
startT = System.currentTimeMillis();
System.out.println("自底向上(动态规划):" + downToTopReslove(TESTCASE));
System.out.println("自底向上(动态规划)用时:" + (System.currentTimeMillis()-startT));
//---线性代数矩阵解斐波那契数列问题测试
int[][] mResult = {{1,1},{1,0}};
startT = System.currentTimeMillis();
int n = 1;
while(n<TESTCASE) {
mResult = matrixMutiple(mResult, matrixUnit);
n ++;
}
System.out.println("线性代数矩阵公式:" + mResult[0][1]);
System.out.println("线性代数矩阵公式用时:" + (System.currentTimeMillis()-startT));
//分治法求m的n连乘测试
System.out.println("分治法求2的23连乘:" + pow(2, 23));
//两矩阵相乘方法测试
/*
int[][] matrix1 = {{2,3,4},{1,2,3}};
int[][] matrix2 = {{2,4},{3,5},{4,6}};
int[][] result = new int[matrix1.length][matrix2[0].length];
int[][] resultS = matrixMutiple(matrix1,matrix2,result);
System.out.println();
*/
}
/**
* 朴素递归
* @param n
* @return 第n个斐波那契数
*/
public static int simpleRecurrence(int n) {
if(n == 0) {
return 0;
}
if(n == 1 || n == 2) {
return 1;
}
return simpleRecurrence(n-1) + simpleRecurrence(n-2);
}
/**
* 自底向上包含"动态规划"思想的解法
* @param n
* @return 第n个斐波那契数
*/
public static int downToTopReslove(int n) {
if(n == 0) {
return 0;
} else if(n == 1 || n == 2) {
return 1;
} else {
int[] fibonacciArray = new int[n+1]; //fibonacciArray[i]表示第i个斐波那契数
fibonacciArray[0] = 0;
fibonacciArray[1] = 1;
fibonacciArray[2] = 1;
for(int i=3;i<=n;i++) { //注意由于fibonacciArray[0]表示第0个元素,这里是i<=n,而不是i<n
fibonacciArray[i] = fibonacciArray[i-1] + fibonacciArray[i-2];
}
return fibonacciArray[fibonacciArray.length-1];
}
}
/**
* 分治法求解factor的n次方
* @param factor 基数
* @param n 次方数
* @return
*/
public static long pow(long factor,int n) {
if(n == 0) {
return 1;
} else if(n == 1){
return factor;
} else {
if(n % 2 == 1) { //乘法数为奇数
return pow(factor,(n-1)/2) * pow(factor, (n-1)/2) * factor;
} else { //乘方数为偶数
return pow(factor, n/2) * pow(factor, n/2);
}
}
}
/**
* 两矩阵相乘
* @param matrix1
* @param matrix2
* @return
*/
public static int[][] matrixMutiple(int[][] matrix1,int[][] matrix2) {
int[][] result = new int[matrix1.length][matrix2[0].length];
for(int i=0;i<matrix1.length;i++) {
for(int j=0;j<matrix2[i].length;j++) {
int temp = 0;
for(int k=0;k<matrix1[0].length;k++) {
temp = matrix1[i][k] * matrix2[k][j] + temp;
}
result[i][j] = temp;
}
}
return result;
}
}
結果:
测试规模:43
朴素递归:433494437
朴素递归用时:1669
自底向上(动态规划):433494437
自底向上(动态规划)用时:0
线性代数矩阵公式:433494437
线性代数矩阵公式用时:1
分治法求2的23连乘:8388608
ここで留意すべきことの一つは、コードがmのn乗に含まれていることであるコード。これは、行列が絶えず液に掛け、第三の線形代数に話したいと思っていた組み合わせが、後でその場合、コードが乱雑に見えるので、彼らは単にさえn回で実現するためにしばらく使用しました。全体的にまだ列数Feibolaqiソリューションの3つの方法を達成するため、我々は我々が参照できることを願っています
Oの友人~~~
再現休暇出典:
ありがとう!
ます。https://my.oschina.net/cjkall/blog/195815で再現