zoukankan      html  css  js  c++  java
  • Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理)

    Leetcode 91. Decode Ways 解码方法(动态规划,字符串处理)

    题目描述

    一条报文包含字母A-Z,使用下面的字母-数字映射进行解码

     'A' -> 1
     'B' -> 2
     ...
     'Z' -> 26
    

    给一串包含数字的加密报文,求有多少种解码方式
    举个例子,已知报文"12",它可以解码为AB(1 2),也可以是L (12)
    所以解码方式有2种。

    测试样例

    Input:
    "0"
    "121212"
    "101010"
    "1001"
    "0101"
    Output:
    0
    13
    1
    0
    0
    

    详细分析

    这道题不难,不过corner cases比较多,需要仔细分析。先考虑1212这个例子:(为了表达方便,我们用逗号分隔表示每种解码方式而不用扳手指算,比如1212的一种解码方式为12,12而不用L,L)

    1=>

    1
    

    12=>

    1,2
    12
    

    121=>

    1,2,1
    1,21
    12,1
    

    1212=>

    1,2,1,2
    1,21,2
    12,1,2
    1,2,12
    12,12
    

    到这里就可以总结出规律了,对于1212,其实是两种解码的和:

    1,2,1,(2)
    1,21,(2)
    12,1,(2)
    -----------
    1,2,(12)
    12,(12)
    

    分割线上面是121的解码方式,并在后加以当前下标的2,分割线下面是12的解码方式加以当前下标和前一个下标表示的字符。

    可以看出,如果当前字符和前面一个字符可以构成>10 && <=26(不包括20,至于为什么等下说)的字符,那么当前解码方式就是:

    dp[i]=dp[i-1]+dp[i-2]
    

    现在考虑一些corner case,如果当前字符是0,那么它并不符合上面的递推公式,考虑2020:
    20=>

    20
    

    202=>

    20,2
    

    2020=>

    20,(20)
    

    可以看到2020,由于0不在解码范围内,所以它不能与前一项通过添加后缀的方式构成解码方式,它只是简单等于前两项然后加上后缀20,同理还有10。

    按照这种思路,我们可以得出下面的状态转移:

    let x = s.substr(i-1,2);
    x>0 && x<10:    dp[i]=dp[i-1]
    x==10:          dp[i]=dp[i-2]
    x>10&&x<20:     dp[i]=dp[i-1]+dp[i-2]
    x==20:          dp[i]=dp[i-2]
    x>20&&x<=26:    dp[i]=dp[i-1]+dp[i-2]
    x>26&&x%10!=0: dp[i]=dp[i-1];
    x>26&&x%10==0: return 0
    
    

    代码实现

    代码太烂凑合看吧...

    class Solution {
    public:
        int numDecodings(string s) {
            if(s.length()==0){
                return 0;
            }
            if(s[0]=='0'){
                return 0;
            }
            if(s.length()==1){
                return 1;
            }
            int dp[100000];
            dp[0]=1;
            std::string ns = s.substr(0,2);
            int t = atoi(ns.c_str());
    
            if(t>0 && t<10){
                return 0;
            }else if(t==10){
                dp[1]=1;
            }else if(t>10 && t<20){
                dp[1]=2;
            }else if(t==20){
                dp[1]=1;
            }else if(t>20 && t<=26){
                dp[1]=2;
            }else if(t>26 && t%10!=0){
                dp[1]=1;
            }else{
                return 0;
            }
            if(s.length()==2){
                return dp[1];
            }
    
            for(int i=2;i<s.length();i++){
                std::string tempStr = s.substr(i-1,2);
                int n = atoi(tempStr.c_str());
    
                if((n>26 && n%10!=0)||(n>0 && n<10)){
                    dp[i]=dp[i-1];
                }else if(n>10 && n<=26&& n!=20){
                    dp[i]=dp[i-1]+dp[i-2];
                }else if(n==10 || n==20){
                    dp[i]=dp[i-2];
                }else if(n==0 || n%10==0){
                    return 0;
                }
            }
            return dp[s.length()-1];
        }
    };
    
  • 相关阅读:
    个人阅读作业+个人总结
    个人作业Week3-案例分析
    个人作业Week2-代码复审
    个人作业-Week1
    个人项目-数独
    第0次个人作业
    团队项目-游戏引擎的考察
    Week3结对项目-数独游戏
    个人作业Week3-案例分析
    代码复审
  • 原文地址:https://www.cnblogs.com/ysherlock/p/8454243.html
Copyright © 2011-2022 走看看