分治法的適用條件:
滿足前三條即可用分治法;如果只滿足前兩條,則考慮用貪心或動態規劃思想;如果還滿足第四條,子問題之間包含公共子問題,此時用分治法的效率比較低,因為公共子問題被重複多次計算,一般使用動態規劃思想比較好。
分治法解題的步驟:
對於上面分治法的適用條件,當滿足條件四時使用分治法求解問題時會重複求解公共子問題,這使得分治法的效率變低了。
動態規劃思想的核心就是在劃分子問題並求解子問題後儲存所有子問題的解,在求解其他子問題時,如果遇到前面已經求解過的子問題(即公共子問題),只需直接查詢我們儲存的該子問題的解即可。
動態規劃思想的有效性依賴於問題本身具有的兩個重要性質:最優子結構性質和子問題重疊性質。
動態規劃演算法的步驟:
採用分治法計算斐波那契數列第n個數時,遞迴的子問題中含有大量重複子問題,主要表現在計算fibonacci(n - 1)和fibonacci(n - 2)時需要計算更小的子問題,而這些子問題被計算過多次,因此效率很低。
#include
#include
using
namespace std;
class
solution};
intmain()
採用動態規劃的方法求斐波那契數列第n個數時,我們從第3個數開始依次向後計算,並儲存前面計算過的子問題的結果,這樣每個子問題只需要計算一次即可,最後從第3個數一直計算到我們所需的第n個數就是結果。
#include
#include
using
namespace std;
class
solution
return r[n -1]
;}};
intmain()
這樣我們的時間複雜度為o(n),空間複雜度也為o(n)。
由於我們最終只需要第n個數的結果,前n-1個數的結果我們並不需要,而上面的計算方法中,我們將前n-1個數的結果都儲存了下來,這對於空間是一種浪費。
我們可以採用迭代更新的方式,只用a1和a2兩個變數記錄每一輪for迴圈時第n-1和第n個數的值。
#include
#include
using
namespace std;
class
solution
return a2;}}
;int
main()
這樣我們的時間複雜度為o(n),空間複雜度為o(1)。
斐波那契數列還可以寫成矩陣乘法的形式:
[ ai
−1ai
−2][
1110
]=[a
iai−
1](i
≥2
)\left[ \begin} & }\end\right] \left[ \begin & \\\\ & \end\right]=\left[ \begin} & }\end\right] \quad(i \geq 2)
[ai−1
ai−
2]
⎣⎡1
110
⎦⎤
=[ai
ai
−1
](i≥
2)於是有:
[ a1
a0](
[111
0])n
−1=[
anan
−1](
n≥1)
\left[ \begin} & }\end\right] \left( \left[ \begin & \\\\ & \end\right] \right)^=\left[ \begin} & }\end\right] \quad(n \geq 1)
[a1a
0]
⎝⎛⎣
⎡11
10
⎦⎤⎠
⎞n−
1=[a
na
n−1
](n
≥1)這樣就把fib數列問題轉化成了乙個求矩陣冪的運算。計算a的n次方最簡單的方法就是a連乘n次,但這樣的時間複雜度為o(n)。我們可以把a的n次方拆成下面的形式:
當n為偶數時
a n=
an/2
an/2
a^=a^ a^
an=an/
2an/
2當n為奇數時
a n=
a(n−
1)/2
a(n−
1)/2
a^=a^ a^
an=a(n
−1)/
2a(n
−1)/
2要求a的n次方,我們先求a的n/2次方,再把n/2的結果平方一下。如果把求n次方的問題看成乙個大問題,把求n/2看成乙個較小的問題。我們可以使用分治法的思路來求a的n次方,這樣就只需要logn次運算。
#include
#include
using
namespace std;
// 定義2x2矩陣
struct matrix2by2
int m_00;
int m_01;
int m_10;
int m_11;};
// 定義2x2矩陣乘法
matrix2by2 matrixmultiply
(const matrix2by2 &matrix1,
const matrix2by2 &matrix2);}
// 分治法計算n個2x2矩陣相乘
matrix2by2 matrixpower
(int n)
else
if(n %2==
0)else
if(n %2==
1)return matrix;
}// 計算斐波那契數列第n個數
intfibonacci
(int n)
;// 如果n為1或2
if(n <=2)
return result[n -1]
; matrix2by2 powernminus2 =
matrixpower
(n -1)
;return powernminus2.m_00;
}int
main()
動態規劃 斐波那契數列
問 大家都知道斐波那契數列,現在要求輸入乙個整數n,請你輸出斐波那契數列的第n項 從0開始,第0項為0 n 39 斐波那契數列簡單介紹 我的解法 注 從fibonacci n 1 fibonacci n 2 明顯看出使用的是遞迴,此題用遞迴兩三行 即可搞定。但是,若出題者準備著乙個超大的n,那麼很有...
分治法例項 斐波那契數列
我們都十分熟悉斐波那契數列的定義 fn fn 1 fn 2,其中f0 0 f1 1。那麼我們如何求解斐波那契數列的某個特定項呢?方法一 遞迴求解。這種方法看似簡單,可是實際上我們會重複計算許多已經計算過的項,最後遞迴樹竟然是一棵完全二叉樹,時間複雜度達到了 n 其中 sqrt 5 1 2。我們不再討...
python斐波那契數列動態規劃
斐波那契類似於1 1 2 3 5 8這樣的數列,當前項等於前兩項之和。根據這個規律就可以用遞迴來做,可是當數字很大的時候,遞迴耗時很長,因此可以採用動態規劃來做。動態規劃 deffeibonacci1 n array 0 1 while len array n 1 array 2 return ar...