java 優化斐波那契數列
阿新 • • 發佈:2018-12-12
一、動態規劃、分治、遞迴的概念
動態規劃:如果大問題分解為很多小問題後,小問題有互相重疊部分,則用遞迴的思路來分析問題,再使用儲存中間結果+迴圈的思路來寫程式碼!動態規劃的三個特徵:適用於最優解問題、有大量的重複子問題、子問題之間有依賴(不獨立)
與遞迴的關係:這些重複的子問題,DP演算法將其結果用一維或二維陣列(鄰接矩陣)儲存下來,等下一次又要計算該子問題時,直接用已計算好的;而遞迴卻不是這樣,它會一遍又一遍地計算這些重複的子問題,從而效率狂降。子問題重複率較高的遞迴演算法可改寫成動態規劃,但不是所有遞迴演算法都適合改成動態規劃。
與分治的關係:在分治法中,有大量的重複子問題,且它們之間無依賴。
二、優化斐波那契數列
package me.ele; /** * 動態規劃的兩種型別 * 1.自頂向下的動態規劃實現:用的遞迴。 * 2.自底向上的動態規劃實現:用的迭代。 * * @author LZJ * @create 2018-09-29 17:29 **/ public class Fibonacci { /** * 普通的遞迴實現的動態規劃:效率特別低,有大量的重複計算,指數級的時間複雜度。 * * @param n * @return */ public static int fibonacci01(int n) { if (n == 0) return 0; if (n == 1) return 1; return fibonacci01(n - 1) + fibonacci01(n - 2); } /** * 自底向上的動態規劃實現:會記錄重複子問題結果的改進版迭代。 * 只要有儲存已經計算出的值的空間,就能把這項技術應用到任何遞迴計算中,就能把演算法從指數級執行時間向線性時間改進。 * * @param n * @return */ public static long fibonacci02(int n) { long temp[] = new long[n]; temp[0] = 0; temp[1] = 1; for (int i = 2; i < n; ++i) { temp[i] = temp[i - 1] + temp[i - 2]; } return temp[n - 1]; } public static long[] mArray; /** * 自頂向下的動態規劃實現:會記錄重複子問題結果的改進版遞迴。儲存它所計算的每一個值(正如下方程式碼最末的步驟), * 並通過檢查所儲存的值,來避免重新計算它們的任何項(正如最初的步驟)。 * * @param n * @return */ public static long fibonacci03(int n) { //不等於初始值0,則表示該元素已經求解過了,直接用其值即可。 if (mArray[n] != 0) { return mArray[n]; } //完成按著遞推式來寫邏輯,即可! if (n == 0) { return mArray[n] = 0; } if (n == 1) { return mArray[n] = 1; } else { return mArray[n] = fibonacci03(n - 1) + fibonacci03(n - 2); } } public static void main(String[] args) { int n = 1000; // System.out.prlongln("==========="); // long start = System.currentTimeMillis(); // System.out.prlongln("start time:" + start); // long fibonacci01 = fibonacci01(n); // System.out.prlongln(fibonacci01); // long end = System.currentTimeMillis(); // System.out.prlongln("end time:" + end + "間隔時間:" + (end - start)); System.out.println("==========="); long start2 = System.currentTimeMillis(); long fibonacci02 = fibonacci02(n + 1); System.out.println(fibonacci02); long end2 = System.currentTimeMillis(); System.out.println("end time:" + end2 + "間隔時間:" + (end2 - start2)); System.out.println("==========="); mArray = new long[n + 1]; long start3 = System.currentTimeMillis(); long fibonacci03 = fibonacci03(n); System.out.println(fibonacci03); long end3 = System.currentTimeMillis(); System.out.println("end time:" + end3 + "間隔時間:" + (end3 - start3)); } }