1. 題目概述
題目如下:
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.
Input: "12"
Output: 2
Explanation: It could be decoded as "AB" (1 2) or "L" (12).
題目的中文意思是給出一個字母和數字的映射,然後給出一串數字,返回對應的合法字母序列的個數.
2. 解題思路
首先用一個例子來分析一下.假設輸入的數字是222,那麼對應的輸出結果是3.從左到右,只有2的時候對應的結果是1,22的時候對應的結果是2,分別爲
2 2-> B B
22 -> V
222對應的結果是3,分別爲
2 2 2-> B B B
22 2 -> V B
2 22 -> B V
在過程中我們可以發現
f(222) = f(22) + f(2)
所以很自然的想到動態規劃.對於第i個數字子串對應的合法字母串數目,等於第i-1個子串和i-2個子串之和,如下所示
f[i] = f[i-1] + f[i-2]
接下來考慮特殊情況,假設輸出的串爲0,那麼對應的輸出應該爲0,因爲這個串無法映射到任意合法的字母串.所以我們知道,當起始字符串字母爲0時,
f[1] = 0 if(s[0] == '0')
同理,接着考慮字符串28,這數字對應的合法字符串爲1,如下所示
2 8 -> B F
28 -> None
28大於26,不對應任何字母.綜上,我們可以得出完整的動態規劃方程式
f[0] = 1
f[1] = (s[0] == '0')?0:1;
f[i] = (s[i]=='0')?0:f[i]+f[i-1]; //如果當前字母不爲0,f[i]+=f[i-1]
f[i] = (s[i-1:s[i]] is valid) ?f[i]=f[i]+f[i-2]:0;//如果s[i-1:i]可以對應合法的字符串,f[i] = f[i] + f[i-2]
3. 題目代碼
該題目的代碼如下所示
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class Solution {
public:
int numDecodings(string s) {
if(s.size() == 0)return 0;
if(s.size() == 1){
if(s[0] == '0')return 0;
else{
return 1;
}
}
vector<int> gV(s.size()+1,0);
gV[0] = 1;
if(s[0] == '0'){
gV[1] = 0;
}
else{
gV[1] = 1;
}
//for(int i=0;i<gV.size();i++)cout<<i<<" "<<gV[i]<<endl;
for(int i=1;i<s.size();i++){
if(s[i] != '0'){
gV[i+1] += gV[i];
}
string sTemp = s.substr(i-1, 2);
//cout<<sTemp<<endl;
if(sTemp[0] != '0' && stoi(sTemp) > 0 && stoi(sTemp) <= 26){
gV[i+1] += gV[i-1];
}
}
return gV[s.size()];
}
};
int main() {
Solution se;
cout<<se.numDecodings("")<<endl;
cout<<se.numDecodings("01")<<endl;
cout<<se.numDecodings("1")<<endl;
cout<<se.numDecodings("11")<<endl;
cout<<se.numDecodings("100")<<endl;
cout<<se.numDecodings("226")<<endl;
return 0;
}