原题地址:https://leetcode.cn/problems/decode-ways/
题解
由于编码最多只到26,因此组合解析的情况最多也只有两个字符
开一个二维数组int[2][s.length()]
,其中:
- dp[0][i]表示第i个字符独立解析的情况下的可能性
- dp[1][i]表示第i个字符和第i-1个字符组合解析的情况下的可能性
对于一般情况,我们可以推出:
- 第i个字符在独立解析的情况下,与第i-1个字符的解析状态无关,可能性为第i-1个字符的两种解析状态可能性之和
- 有dp[0][i]=dp[0][i-1]+dp[1][i-1]
- 第i个字符在组合解析且组合情况符合要求[10,26]的情况下,则继承第i-1个字符独立解析的状态的可能性
- 第i个字符在组合解析的情况下,若组合情况不符合[10,26],则表示不能与第i个字符组合解析
考虑几个特殊情况:
- 当第i个字符为0时,只能采用组合解析的情况,0无法被独立解析
- 有dp[0][i]=0;
- 当组合解析的情况即dp[1][i]也为0时,由于第i个字符的可能性仅与第i-1个字符有关,因此最终输出结果必然是0,可以直接返回0
- 当为第一个字符时,自然无法与前一个字符组合解析,所以有
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Solution { public int numDecodings(String s) { int[][] dp=new int[2][s.length()]; for(int i=0;i<s.length();i++){ if(s.charAt(i)=='0'){ if(i==0)return 0; dp[0][i]=0; if((s.charAt(i-1)-'0')*10+(s.charAt(i)-'0')>=10&&(s.charAt(i-1)-'0')*10+(s.charAt(i)-'0')<=26) dp[1][i]=dp[0][i-1]; else return 0; }else if(i==0){ dp[0][i]=1; dp[1][i]=0; }else{ dp[0][i]=dp[0][i-1]+dp[1][i-1]; if((s.charAt(i-1)-'0')*10+(s.charAt(i)-'0')>=10&&(s.charAt(i-1)-'0')*10+(s.charAt(i)-'0')<=26) dp[1][i]=dp[0][i-1]; else dp[1][i]=0; } } return dp[1][dp[1].length-1]+dp[0][dp[0].length-1]; } }
|
观察代码发现,当遍历到i时,dp[x][i]的状态仅与dp[x][i-1]有关,因此可以只用两个变量滚动来完成迭代
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| class Solution { public int numDecodings(String s) { int combined=0,uncombined=1,tmp; if(s.charAt(0)=='0')return 0; for(int i=1;i<s.length();i++){ if(s.charAt(i)=='0'){ if(i==0)return 0; if((s.charAt(i-1)-'0')*10+(s.charAt(i)-'0')>=10&&(s.charAt(i-1)-'0')*10+(s.charAt(i)-'0')<=26) combined=uncombined; else return 0;
uncombined=0; }else{ tmp=combined+uncombined; if((s.charAt(i-1)-'0')*10+(s.charAt(i)-'0')>=10&&(s.charAt(i-1)-'0')*10+(s.charAt(i)-'0')<=26) combined=uncombined; else combined=0;
uncombined=tmp; } } return combined+uncombined; } }
|