91. Decode Ways
思路:
这种每个问题元素有多个解的问题还是用动态规划。
那么我们从最后开始想,如果但用最后一个字符,那么就要保证他不为0即可。那么i位置的解码方案就应该加上前一个位置的解码方案。第一次对i位置的加,dpi是等于0的,所以此时dpi=dpi-1,转移方程就为 dpi=dpi-1;
如果用最后两个字符,那么就要保证前一个字符不为0,并且两者小于等于26,同时要确保有两个元素,那么就要求此时的字符位置应该是大于等于第三个字符位置。那么i位置的解码方案就和前面第二个的方案相同,当然应该是加上,因为我们之前在i位置就加上了只用最后一个字符的解码方案,转移方程为 dpi=dpi-2;
考虑边界条件就是当字符为空的时候那么就只有1个解码方法。
那么我们定义一个dp数组,dp[0]=1,即要是字符串s为空,那么就返回1.
代码:
class Solution {
public:
int numDecodings(string s) {
int n=s.length();
vector<int> dp(n+1);
dp[0]=1;
for(int i=1;i<=n;++i){
if(s[i-1]!='0'){
dp[i] +=dp[i-1];
}
if(i>1&&s[i-2]!='0'&&(s[i-2]-'0')*10+(s[i-1]-'0')<=26){
dp[i] += dp[i-2];
}
}
return dp[n];
}
};
可以看到我们对一个数组同时之操作三个元素,那么我们用三个变量来等效上述用法即可节省数组的空间。
优化:
class Solution {
public:
int numDecodings(string s) {
int n=s.length();
int dp1=0,dp2=1,dp3=0;
for(int i=1;i<=n;++i){
dp3=0;
if(s[i-1]!='0'){
dp3=dp2;
}
if(i>1&&s[i-2]!='0'&&(s[i-2]-'0')*10+(s[i-1]-'0')<=26){
dp3 += dp1;
}
tie(dp1,dp2)={dp2,dp3};
//dp1=dp2;
//dp2=dp3;
}
return dp3;
}
};