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;
    }
};
posted @ 2021-04-22 00:18  Mrsdwang  阅读(26)  评论(0编辑  收藏  举报