到底怎麼學動態規劃?
回想起當初學動態規劃的時候,是真的難。動態規劃的確很難,很考驗邏輯思惟能力、抽象能力、還有數學建模能力。 可是入門動態規劃真的有這麼難嗎?我覺的其實真的不難,就是單純的找規律;這裏我想以一種比較野路子的方式幫助你們入門理解動態規劃,這種方法真的是很簡單且有效果,大神請忽略。markdown
DP table
什麼方法呢?直接畫表格,找規律。 這個辦法在不少題目下都是很是的有效果,特別是矩陣型dp,簡直是萬金油;這種方法很是簡單,你只須要記住兩個技巧。spa
- 把問題的規模變小,變成小問題思考
- 根據小問題來填表格,找出規律
記住這兩個技巧,下面我以一道相對簡單,一道稍微難一點的真題還講解。code
62.不一樣路徑
首先分析一下題目,題目說機器人只能往下,或者往右走,到達右下角有多少種走法。
- 不要單純的幹想,單純的幹想會浪費不少的時間,甚至手足無措,徹底不知道怎麼辦了,直接畫表格找規律,這裏我以一個5*7的表格來舉例。
- 首先爲何第一行第一列全是1?由於若是隻有第一行第一列,機器人就只有一條路可走。
- 回憶一下上面兩個技巧;假設咱們把網格變小,也就是把問題的規模變小,變成一個3*3的表格。
- 3*3 有多少種走法很簡單吧?直接把表格填完就能夠獲得答案了,答案就是6種。
- 爲何是6種呢?由於機器人只能往右或者往下走,到達3 * 3的最右下角,只能往上面下來,或者左邊過來。
- 那若是把問題的規模繼續變大,變成4*4的表格呢?咱們繼續填表
- 繼續觀察答案,答案是20種;那有什麼規律呢?我相信沒有人會發現不了這個規律吧?
- 很明顯,table[3][3] = table[2][3] + table[3][2],也就是說機器人走到規模爲4 * 4的網格右下角有20種走法。
書寫代碼
到這裏,我相信寫出代碼應該不難了吧?orm
var uniquePaths = function (m, n) {
// 由於第一行第一列都是1
let dp = Array.from(new Array(m), () => new Array(n).fill(1))
for(let i = 1; i < m; i++){
for(let j = 1; j < n; j++){
// 當前的等於上面的(dp[i - 1][j])+ 左邊的(dp[i][j - 1])
dp[i][j] = dp[i - 1][j] + dp[i][j - 1]
}
}
return dp[m - 1][n - 1]
};
複製代碼
其實動態規劃也就這麼簡單,就是單純的畫表格找規律。數學
1143.最長公共子序列
- 分析下題目,要找兩個串的最長公共子序列,不要多想。直接畫表格觀察規律
- 爲何會有空串?爲何空串對應的都是0?你想呀,須要從無到有推導出答案,找出規律,因此須要藉助空串;若是兩個串中的其中一個爲空,那確定都是0呀。
- 由於用例的答案是3,全部我先把結果先上去,好利用這個結果來找出規律。
- 咱們繼續填表推導,找出規律。
- 當問題的規模變大,text1[0] == text2[0],答案很明顯是1。這裏咱們就發現了相等的時候要加1了,好傢伙,繼續觀察。
- 爲何我會先填 text1[0] == text2[0] 對應的行和列呢?由於當text1/text2的長度繼續變長的時候,最終的結果會受影響嗎?很明顯,不受影響,繼續填表找規律。
- 當咱們填到text1[i] == text2[j],也就是c字符相等的時候,由以前找到的規律,它必定要加1,可是在哪一個基礎上加1呢?很明顯是問題的規模變小的時候,也就是沒有c這個字符的時候,也就是表格的table[1][2],綠色區域爲1的塊。
- 繼續以這個規律填表格看看,咱們看紅色塊。
- 最終驗證了答案,當兩個字符相等的時候,就等於上一個規模小的問題加1,不想等的就至關於有沒有這個字符都同樣。取兩個串少一個的狀況下的最大值就能夠了。
- 因此規律以下:
- text1[i] == text2[j], table[i][j] = table[i - 1][j - 1] + 1
- text1[i] != text2[j], table[i][j] = max(table[i - 1][j], table[i][j - 1])
書寫代碼
var longestCommonSubsequence = function(text1, text2) {
let n = text1.length
let m = text2.length
let dp = Array.from(Array(n + 1), () => Array(m + 1).fill(0))
//空串都是0,0不用看了
for(let i = 1; i <= n; i++){
for(let j = 1; j <= m; j++){
if(text2[j - 1] == text1[i - 1]){
dp[i][j] = dp[i - 1][j - 1] + 1
}else{
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1])
}
}
}
return dp[n][m]
};
複製代碼
總結
其實這種辦法寫動態規劃是很是野路子的,可是對於新手來講,入門確實不錯。 動態規劃確實有點難,把它講明白,講清楚也不簡單,但願我這篇水文能幫助你更好的理解動態規劃吧。互聯網人共勉~it