DP動態規劃專題一 :LeetCode 91. Decode Ways
LeetCode 91. Decode Ways
A message containing letters from A-Z is being encoded to numbers using the following mapping:
‘A’ -> 1
‘B’ -> 2
…
‘Z’ -> 26
Given a non-empty string containing only digits, determine the total number of ways to decode it.
Example 1: Input: "12" Output: 2 Explanation: It could be decoded as "AB" (1 2) or "L" (12).
Example 2:
Input: "226"
Output: 3
Explanation: It could be decoded as "BZ" (2 26), "VF" (22 6), or "BBF" (2 2 6).
解決動態規劃問題最主要的就是得到動態規劃的公式,思路還是用數學歸納法,先假設0~n-1已經完成,看看怎麼通過0 - n-1來推n,這個時候,如果n的答案至少依賴於n-1和n-2的答案時,資料結構就成了圖,除了分叉還有交叉,這時候就可以用hashmap儲存0 - n-1的答案,每次在後面需要時就可以直接得到。而hashmap又可以簡化為陣列的偽雜湊表來存放答案。這就是為什麼我們會看到有些題是用陣列來記錄的,好處在於陣列可以bulk load,優化時間。這道題的關鍵在於,怎麼更新這個可能的個數,先假設不存在0,那麼就需要判斷i與i-1的關係,如果i-1和i構成的數字小於等於26,那麼可能的個數是dp[i] = dp[i-1] + dp[i-2], 因為兩個數字可以結合一起decode,也可以分開decode;如果大於26,只能分開decode,dp[i] = dp[i-1],這樣就得到了公式。在此之上再考慮0的問題即可。
動態規劃公式:dp[n] = Math.max(composite <= 26 ? dp[n-2] + dp[n-1] : dp[n-1])
public int numDecodings(String s) { //dp[n] = Math.max(composite <= 26 ? dp[n-2] + dp[n-1] : dp[n-1]) if (s.length() == 0) return 0; if (s.charAt(0) == '0') return 0; int[] dp = new int[s.length() + 1]; dp[0] = 1; dp[1] = 1; for (int i = 1; i < s.length(); i++) { int cur = (s.charAt(i-1) - '0') * 10 + s.charAt(i) - '0'; if (s.charAt(i) == '0') { if (s.charAt(i-1) == '0' || cur > 26) return 0; dp[i+1] = dp[i-1]; continue; } if (s.charAt(i-1) == '0') { dp[i+1] = dp[i]; continue; } dp[i+1] = cur > 26 ? dp[i] : dp[i] + dp[i-1]; } return dp[s.length()]; }
在正確的基礎上進行優化,由於n只和n-1和n-2有關,因此在更新的過程中,實際只有兩個值在發揮作用,因此我們可以省去陣列而只用兩個值進行更新。程式碼如下:
public int numDecodings(String s) {
//dp[n] = Math.max(composite <= 26 ? 2 * dp[n-2] : dp[n-2], dp[n-1])
if (s.length() == 0) return 0;
if (s.charAt(0) == '0') return 0;
int i_2 = 1;
int i_1 = 1;
for (int i = 1; i < s.length(); i++) {
int cur = (s.charAt(i-1) - '0') * 10 + s.charAt(i) - '0';
int i_0 = 0;
if (s.charAt(i) == '0') {
if (s.charAt(i-1) == '0' || cur > 26) return 0;
i_0 = i_2;
} else if (s.charAt(i-1) == '0') {
i_0 = i_1;
} else {
i_0 = cur > 26 ? i_1 : i_1 + i_2;
}
i_2 = i_1;
i_1 = i_0;
}
return i_1;
}