動態規劃:經過分解問題,將複雜的問題分解爲最基本的小問題,找到局部的最優解,而後找到最終問題的最優解的過程。java
動態規劃關鍵:程序員
案例選自 極客時間 程序員的數學基礎課數組
查詢推薦須要注意的點app
下邊拿兩個單詞來進行舉例搜索引擎
字符串A:kobbespa
字符串B: kobecode
表格裏邊記錄的是兩個字符串的編輯距離遞歸
- - | -空串B- | -k- | -o- | -b- | e |
---|---|---|---|---|---|
空串A | 編輯距離0 | (增長一個字符編輯距離+1)1 | 2 | 3 | 4 |
k | 1 | min(2,2,0)=0 | min(3,1,2)=1 | min(4,2,3)=2 | min(5,3,4)=3 |
o | 2 | min(1,3,2)=1 | min(2,2,0) = 0 | min(3,1,2)=1 | min(4,2,3)=2 |
b | 3 | min(2,4,3) = 2 | min(1,3,2) = 1 | min(2,2,0)=0 | min(3,1,2)=1 |
b | 4 | min(3,5,4) =3 | min(2,4,3)=2 | min(1,3,2) =1 | min(2,2,1)=1 |
e | 5 | min(4,6,5) =4 | min(3,5,4)=3 | min(2,4,3)=2 | min(2,3,1) =1 |
如圖所示最優解就爲1索引
狀態轉移方程字符串
i == 0 和 j==0 這裏就不作贅述。
i>0 和 j>0 的狀況。
d[i,j] = min(d[i,j+1] + 1 , d[i+1,j]+1 , d[i,j] + r(i,j) ). {添加的字符相等 r(i,j) = 0,不然r(i,j)=1}
代碼以下:
// 實現狀態轉移方程
// 請注意因爲 Java 語言實現的關係,代碼裏的狀態轉移是從 d[i, j] 到 d[i+1, j+1],而不是從 d[i-1, j-1] 到 d[i, j]。本質上是同樣的。
for (int i = 0; i < a.length(); i++) {
for (int j = 0; j < b.length(); j++) {
int r = 0;
if (a.charAt(i) != b.charAt(j)) {
r = 1;
}
int first_append = d[i][j + 1] + 1;
int second_append = d[i + 1][j] + 1;
int replace = d[i][j] + r;
int min = Math.min(first_append, second_append);
min = Math.min(min, replace);
d[i + 1][j + 1] = min;
}
}
return d[a.length()][b.length()];
}
}
複製代碼
假設有 三種幣種 2,5,7 求這三種幣種組成 100 元 用的最小的紙幣張數。
方程以下:
c[totalMoney] = c[totalMoney - moneyKind()] + 1;
代碼以下:
private static int totalNumberForMoney(int[] moneyKind,int total){
//初始化 c數組
int[] c = new int[total+1];
for(int i=1;i<c.length;i++){
c[i] = -1;
}
c[0] = 0;
for(int i=1;i<=total;i++){
int[] data = new int[moneyKind.length];
for(int j = 0;j<moneyKind.length;j++){
if((i - moneyKind[j])<0){
data[j]= -1;
continue;
}
data[j] = c[i - moneyKind[j]];
}
int min = min(data);
if(min == -1){
continue;
}
c[i] = min + 1;
System.out.println(i + "min" + c[i]);
}
return c[total];
}
private static int min(int[] data) {
boolean flag = true;
int min = -1;
for(int i=0;i<data.length;i++){
if(data[i]==-1){
continue;
}
if(flag){
min = data[i];
flag = false;
continue;
}
if(data[i]<min){
min = data[i];
}
}
return min;
}
複製代碼
動態規劃的適用場景:
**最小值,最大值,最優解,最段子串,最長子串.....**等等
解決動態規劃問題的關鍵就是寫出 問題轉移的方程,而後轉換成程序。
並且動態規劃的時間複雜度 爲mn 若是相同的問題使用遞歸循環(排列組合)進行解的話,考慮的各類複雜的狀況須要窮舉出全部的可能隨着數據量的增長時間複雜度要比mn大的多。