您的位置:首页 > 其它

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

2018-02-19 19:05 260 查看

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];
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: