91-解码方法-细节决定成败

作者: 华雨欣 | 来源:发表于2020-05-02 13:23 被阅读0次

写在前面

这是一道比较简单的DP问题,定义dp数组和寻找递推方程都很容易,不过多种情况实在是不太容易考虑周全,做题都成了从用例推情况了,思路实在是不太清晰。

题目

核心思路

题目求解给定字符串的解码方法总数,那么很容易就可以想到,dp[i]表示从字符串开头至i下标的解码方法总数,有了定义,可以来看下面的例子,寻找递推方程。

在上图中,绿色表示未发生合并,直接在前一个子串的基础上新增一个字符;红色表示发生合并,合并后的字符需要加在前两个子串的末尾,由此,很容易想到如下的递推公式:
//可发生合并
dp[i] = dp[i - 2] + dp[i - 1];
//不可发生合并
dp[i] = dp[i - 1];

似乎这样就可以解决了,不过在我提交的时候发现少考虑了很多情况:

  • 当前位置为'0',且可以组成10,20...
  • 当前位置为'0',组成00
  • 当前位置不为'0',且前一位为'0',如01,02...
  • 当前位置不为'0',且前一位与当前一位组成27,38...
    这些情况考虑不到终归是得不到正确的结果的。

代码

很惭愧,上边的情况考虑的只考虑到了最后一种,然后根据用例添加情况判断后得到了这样的代码:

class Solution {
    public int numDecodings(String s) {
        if(s == null) return 0;
        int n = s.length();
        if(n < 2 && s.charAt(0) != '0') return 1;
        else if(s.charAt(0) == '0') return 0;

        int[] dp = new int[n + 1];
        dp[0] = 1;dp[1] = 1;
        for(int i = 2; i <= n; i++){
            if(s.charAt(i - 1) == '0'){
                if(s.charAt(i - 2) > '2' || s.charAt(i - 2) == '0'){
                    return 0;
                }else{
                    dp[i] = dp[i - 2];
                }
            }else{
                if(s.charAt(i - 2) == '0'){
                    dp[i] = dp[i - 2];
                }else{
                    int temp = (s.charAt(i - 2) - '0') * 10 + (s.charAt(i - 1) - '0');
                    if(temp <= 26){
                        dp[i] += dp[i - 2];
                    }
                    dp[i] += dp[i - 1];
                }
            }
        }
        return dp[n];
    }
}

虽然成功通过了,但是逻辑并不是很清晰,后来通过看官方推荐1ms的题解,才发现这些情况其实都是可以合并的,只要一个条件就可以解决,代码如下:

class Solution {
    public int numDecodings(String s) {

        if(s == null || s.length() == 0){
            return 0;
        }
        int[] dp = new int[s.length() + 1];
        dp[0] = 1;
        dp[1] = s.charAt(0) == '0' ? 0 : 1;
        for(int i = 2; i <= s.length(); i++){
            if(s.charAt(i - 1) != '0'){
                dp[i] = dp[i - 1];
            }
            int twodigits = (s.charAt(i - 2) - '0') * 10 + s.charAt(i - 1) - '0';
            if(twodigits >= 10 && twodigits <= 26){
                dp[i] += dp[i - 2];
            }
        }
        return dp[s.length()];
    }
}

每每看到别人简单的代码总会羡慕,不过那都是一点点完善合并出来的,希望自己可以在变强的路上越走越远吧。如果有写的不对的地方还请指出,感恩相遇~

相关文章

网友评论

    本文标题:91-解码方法-细节决定成败

    本文链接:https://www.haomeiwen.com/subject/iakkghtx.html