1. 程式人生 > >java 優化斐波那契數列

java 優化斐波那契數列

一、動態規劃、分治、遞迴的概念

     動態規劃:如果大問題分解為很多小問題後,小問題有互相重疊部分,則用遞迴的思路來分析問題,再使用儲存中間結果+迴圈的思路來寫程式碼!動態規劃的三個特徵:適用於最優解問題、有大量的重複子問題、子問題之間有依賴(不獨立)

     與遞迴的關係:這些重複的子問題,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));

    }

}