91. 解码方法

Smile_slime_47

原题地址: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个字符独立解析的状态的可能性
    • 有dp[1][i]=dp[0][i-1]
  • 第i个字符在组合解析的情况下,若组合情况不符合[10,26],则表示不能与第i个字符组合解析
    • 有dp[1][i]=0

考虑几个特殊情况:

  • 当第i个字符为0时,只能采用组合解析的情况,0无法被独立解析
    • 有dp[0][i]=0;
    • 当组合解析的情况即dp[1][i]也为0时,由于第i个字符的可能性仅与第i-1个字符有关,因此最终输出结果必然是0,可以直接返回0
  • 当为第一个字符时,自然无法与前一个字符组合解析,所以有
    • dp[0][i]=1;dp[1][i]=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;
}
}
Comments
On this page
91. 解码方法