算法设计与分析第十三周——动态规划之Decode Ways

15 篇文章 0 订阅
5 篇文章 0 订阅

算法设计与分析第十三周——动态规划之Decode Ways

      这周选择的题目比较简单,题目链接为:Decode Ways


题目详情

      题目为给定一个只包含 ‘0’ - ‘9’的字符串s,并且给定一种解码格式:‘1’ -> 'A','2' -> 'B','3' -> 'C',...,‘26’  -> 'Z',问所给的字符串能够得到多少种解码结果。

      样例分析:

输入输出解释
"12"
2

结果1:‘1’、‘2’分开解码,分别解码为‘A’、‘B’

结果2:‘12’被直接解码为‘L’

“226”3

结果1:分开"22"和"6"解码,解码为'V'、'F'

结果2:分开"2"和"26"解码,解码为'B'、'Z'

结果3:分开为"2"、"2"、"6",解码为'B'、'B'、'F'


题目分析与算法设计

      显而易见的,就是要我们找出给定字符串s中的所有字面数值大于0小于27子串集合的个数,此时,从后往前遍历s,查找所有可能的情况,一次查找两位,如果这两位的字面数值满足大于0小于27,那么我们可以对这两位数中的后一位数计算得到的结果加上之前的结果数,即是从这两位数中的第一位数往后一直到s尾部的满足条件的子串集合的个数;如果不满足条件,那么只能向之前子串集合中加入当前遍历到的数,而不会产生多的子串集合。

      比如,输入s为"2526",从后往前遍历:

  1. 遍历最后一个字符是只有集合 {'6'},结果为1,遍历到‘2’,因为查找的两位为"26",故集合为 {‘2’,'6'} 和 {"26"};
  2. 遍历到'5',查找的两位为"52",大于27了,说明"52"不能组在一起进行解码,而只能把'5'加入原有的就和中,形成 {‘2’,'6','5'} 和 {"26",'5'};
  3. 遍历到'2',查找的两位为"25",可以分别拆分成'2'、'5'或组合成"25"进行解码,那么,就形成了4个子串集合了,因为遍历到字符串后面的'2'时有两种情况,遍历到'5'时也有两种情况,相加即可。

      那么,可以创建一个dp数组,长度为字符串长度加1,dp[ i ] 表示从下标 i 开始到 s 尾部的所有子串集合的个数,dp[s.size()]初始化为1,因为一个字符时只有一种结果,当然,如果 s[ s.size() - 1 ] 为'0',则dp[s.size() - 1] = 1,因为字符‘0’不能解码,由上述分析,可以很容易得到状态转移方程:

  • dp[i] = dp[i+1] +dp[i+2] if s[i, i+2] > "00" and  s[i, i+2] < "27";
  • dp[i] = dp[i+1].

     dp[0] 即为所求。


代码详情

    int numDecodings(string s) {
        int n = s.size();
        int dp[n + 1] = {0};
        dp[n] = 1;
        if (s[n-1] != '0') {
            dp[n-1] = 1;
        }
        
        for (int i = n - 2; i>= 0; i --) {
            if (s[i] == '0') continue;
            // if s[i, i + 2] < 27, we can get dp[i] by adding dp[i+1] and dp[i+2]
            if (stoi(s.substr(i, 2)) <= 26) {
                dp[i] = dp[i + 1] + dp[i + 2];
            }
            else {
                dp[i] = dp[i + 1];
            }
        }
        return dp[0];
    }

      代码只需一个循环,时间复杂度为O(n),只需维护一个dp数组,空间复杂度也为O(n)。


      谢谢阅读。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值