一、問題
看乙個經常被引用的問題
例子1:1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1=?
例子2:1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1+1=?
問你例子1是多少時,你乙個個算後,結果是20
接著問你例子2時,你會馬上說出21,為什麼第二次這麼快?
因為我們將前面已經計算好的結果儲存下來,後面計算的時候再次使用,就不需要重複計算了。(一種典型的用空間換時間思想)
二、什麼是動態規劃(dynamic programming)
動態規劃在尋找有重疊子問題的最佳解時,將問題重新組合成子問題,為避免多次解決這些子問題,它們的結果都被計算並儲存,先求解出子問題的最優解,再結合子問題的最優解求出整個問題的最優解。
2.1、什麼時候用動態規劃
動態規劃演算法通常用於求解具有某種最優性質,子問題重疊的問題。
2.2、如果使用動態規劃?主要思考三個問題。
1.定義dp陣列,找出dp陣列的含義
2.找出 dp[n]和dp[n-1]之間的關係
3.找出陣列的初始值dp[0]=? dp[1] = ?
三、通過例子來理解動態規劃
1、先來看乙個斐波那契數列,求它的第n項:
求解一:斐波那契數列的定義如下:
f(0) = 0, f(1) = 1
f(n) = f(n - 1) + f(n - 2), 其中 n > 1.
用遞迴去求解,樹形遞迴的時間複雜度是o(2^n)。
求解二:
用動態規劃求解:
找出三個主要的關係後,問題的解也迎刃而解。時間複雜度為o(n)。/**
* 1.dp[n]就表示第n項的值
* 2.陣列關係很明顯,dp[n] = dp[n-1]+dp[n-2];
* 3.初始值dp[0] = 0 ;dp[1] = 1;
*/public class solution
int dp = new int[n+1];
dp[0] = 0;
dp[1] = 1;
for(int i=2;i<=n;i++)
return dp[n];
}}
2.求連續子陣列的最大和(leetcode的42題)
考慮三個問題輸入乙個整型陣列,陣列裡有正數也有負數。陣列中的乙個或連續多個整數組成乙個子陣列。求所有子陣列的和的最大值。
要求時間複雜度為o(n)。
示例1:
輸入: nums = [-2,1,-3,4,-1,2,1,-5,4]
輸出: 6
解釋: 連續子陣列 [4,-1,2,1] 的和最大,為 6。
①dp陣列的含義,這裡dp[n]我們表示輸入陣列,第n項結尾的連續陣列的最大和。
比如輸入nums = [4,-2] ,dp[1] = 2;存的是4+(-2)=2而非4,因為是以n項結尾的連續陣列。
②找出陣列的之間的關係
<1> 根據陣列含義,不難推出
dp[n] = dp[n-1] + nums[n];
<2>如果上式中dp[n-1]<0;那麼dp[n] = nums[n]即可
③初始值,dp[0] = nums[0]
求解的所有子陣列的和的最大值,從dp陣列中遍歷即可。
4.01揹包問題class solution
}dp[i] = submaxdp +1; //要麼長度是1,要麼在上公升子串行最長的後面+1;
resmax = math.max(resmax,dp[i]); //dp陣列中最大值,也即最長的上公升子串行
}return resmax;
}}
有n件物品和乙個容量為v的揹包。第i件物品的重量是w[i],價值是v[i]。求解將哪些物品裝入揹包可使價值總和最大
比如有4個物品,揹包容量capacity= 8,重量分別為 w = [2,3,4,5],價值分別 v = [3,4,5,6],
輸出: 10
解釋: 裝重量為3和5的兩個物品,價值等於10.
之所以叫01揹包,是物品要麼拿,那麼不拿,不存在拿一半的情況(物品完整)。
①定義dp陣列,dp[n][c],表示n個物品時,容量為c的最大價值。
②陣列關係
<1>如果包的容量比物品小,裝不下,價值就等於前n-1個物品。
dp[n][c] = dp[n-1][c];等於裝與不裝。
<2>如果包可以裝下該物品,那它的價值就等於該物品價值v[n]加上裝過該物品剩餘容量(c-w[n])還能裝下的最大價值(子問題的解,dp[n-1][c-w[n]])。
即dp[n][c] = v[n]+dp[n-1][c-w[n]];
物品\容量01
2345
6780
0000
0000
01(2,3)00
3333
3332(3,4)
0034
47777
3(4,5)00
345?
4(5,6)
說明:第二行0個物品,很明顯,不管包的容量為多少,價值都為0;其他根據陣列關係不難填出其他。
我們發現裝第三個(4,5)物品,包容量為5時,dp[3][5] = v[3] + dp[2][1] = 5 + 0 = 5,價值還不如不裝(dp[n-1][c])的價值.
所以取最優解dp[n][c] = math.max(v[n]+dp[n-1][c-w[n]],dp[n-1][c]);
<3>初始值
dp[0][c] = 0;//物品為0時,包容量再大,價值也是為0
dp[n][0] = 0;//包容量為0,物品再多也裝不了,價值為0
理解這些後,**也就出來了
public class solution{
public int zeroonepack(int c,int w,int v){
if(w == null || w.length == 0) return 0;
int dp = new int[w.length][c+1];
for(int i = 1;i最後我們在回過頭來什麼是動態規劃:
動態規劃就是解決最優化問題的方法,通常用於求解具有某種最優性質,子問題重疊的問題,求解出子問題的最優解,再結合子問題的最優解求出整個問題的最優解。
聊一聊小甜餅
cookies程式設計 cookie是儲存在客戶端的小文字,儲存的位置分為兩種 cookie可能儲存在客戶端瀏覽器的所佔記憶體中,關閉瀏覽器後,cookies就不再存在。cookie也可能儲存在客戶pc機的硬碟上,設定有效時間,超過有效時間後失效。cookie的常見應用 簡化登入 很多 在登入時,可...
聊一聊元資料
這個話題來自我的msn space。這是原文 元資料 metadata 這個詞現在到處氾濫。其實我對元資料充其量只能說有自己的理解而已,並不能確信這個理解是正確的。我認為,資料結構分為三個層次 uml可是四層哦 例項層 直接描述特異化的資料場景 元資料層 描述例項的結構的一組資料 元資料的元資料層 ...
聊一聊 Nginx 變數(一)
變數可以認為是存放 值 的容器。而所謂 值 在許多程式語言裡,既可以是3.14這樣的數值,也可以是hello world這樣的字串,甚至可以是像陣列 雜湊表這樣的複雜資料結構。nginx 的變數和 perl php 等語言的類似,由美元符號 開頭,隨後跟著乙個字串,代表這個變數的名稱,例如 name...