LeetCode刷题笔记(Decode Ways)

刚吃完中饭,试了试外面的风力,还好我还比较胖风都动不了我。下面就和大家分享一下刚刷的这道题。

题目如下:

题意分析: 

假如有一个由‘A-Z’字母构成的消息且可以通过'A' -> 1,'B' -> 2...'Z' -> 26的方式进行编码得到一组由数字构成的消息,现有一组由数字构成的消息,请将其解码成一个由‘A-Z’字母构成的消息,其中‘0’不可以解码,且最多只能对两位进行解码。

方法一(动态规划法)

本方法需要维护一个 dp 数组,其中 dp[i] 表示s中前i个字符组成的子串的解码方法个数(dp长度=输入字符串长度+1),并将 dp[0] 初始化为1。状态转移方程为 dp[i](前i个字符组成的子串的解码方法个数) = dp[i-1](前i-1个字符组成的子串的解码方法个数) + dp[i-2](前i-2个字符组成的子串的解码方法个数)。具体分析如下:若当前位置是0,那么一定不可以解码,即不能加上 dp[i-1],就只有看是否能与前一个数字组成大于等于 10 且小于等于 26 的数,若可以则可以加上 dp[i-2],否则 dp[i] 就只能为0。具体的操作如下:在遍历的过程中,对每个数字首先判断其是否为0,若是则将 dp[i] 赋为0,若不是则赋上 dp[i-1] 的值,然后看数组前一位是否存在,如果存在且满足前一位是1,或者与当前位一起组成的两位数不大于 26,则当前 dp[i] 值加上 dp[i - 2]。最后返回 dp 数组的最后一个值即可。

解题代码如下:

class Solution{
public:
    int numDecodings(string s){
        if ( s.size() == 0 || s[0] == '0') return 0;
        vector<int> dp( s.size() + 1, 0 );
        dp[0] = 1;
        for (int i = 1; i < dp.size(); i++) {
            //若当前数字为0,则无法解码,故只有0种解码方法
            if ( s[i-1] == '0' ) dp[i] = 0;
            //若当前数字不为0,则至少可以有与 dp[i-1] 一样多的解码方法
            else dp[i] = dp[i-1];
            //若当前数字能与前一个数字组成大于等于 10 且小于等于 26 的数,则可以有 dp[i-1] + dp[i-2] 种解码方法
            if ( i > 1 && (s[i-2] == '1' || ( s[i-2] == '2' && s[i-1] <= '6' )) ) dp[i] += dp[i-2];
        }
        return dp.back();
    }
};

提交后的结果如下: 

 

方法二(优化方法一)

与方法一的思路大体一致,但是通过优化了方法一中的一些逻辑,减少了代码量。

注:substr()函数取到的是字符串,所以比较的对象不能是单个字符。

解题代码如下:

class Solution{
public:
    int numDecodings(string s){
        if ( s.size() == 0 || s[0] == '0') return 0;
        vector<int> dp( s.size() + 1, 0 );
        dp[0] = 1;
        for (int i  = 1; i < dp.size(); i++) {
            //若当前数字不为0,则至少可以有跟 dp[i-1] 一样多的拆分情况
            if ( s[i-1] != '0' ) dp[i] = dp[i-1];
            //若当前数字能与前一个数字组成大于等于 10 且小于等于 26 的数,则可以有 dp[i-1] + dp[i-2] 种解码方法
            if ( i > 1 && (s.substr(i-2, 2) <= "26") && (s.substr(i-2, 2) >= "10")) dp[i] += dp[i-2];
        }
        return dp.back();
    }
};

 提交后的结果如下: 

 

 

 

日积月累,与君共进,增增小结,未完待续。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值