leetcode 91. Decode Ways
A message containing letters from A-Z is being encoded to numbers using the following mapping:
'A' -> 1
'B' -> 2
...
'Z' -> 26
Given an encoded message containing digits, determine the total number of ways to decode it.
For example,
Given encoded message “12”, it could be decoded as “AB” (1 2) or “L” (12).
The number of ways decoding “12” is 2.
题意说明,将A-Z 26个英文字母对应成为1-26个数字,当拿到一个英文字符串的时候,很容易将其对应成为一串数字,题目是给出一串数字,然后让你计算出可以转化成为这个数字串的不同英文字符串有多少个。
与王印讨论的思路。
首先,先进行定义,定义dp[i]的含义为,前i个数字能够对应多少个不同的字符,然后进行递推。
列出26个数字,从中发现一些规律。
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
第一个特殊点,如果当前字符为0,则左边必须为1或者2。
第二个特殊点,如果左边为1,当前字符为1-9,则有两种对应关系。
第三个特殊点,如果左边为2,当前字符为1-6,则有两种对应关系。
根据分析,就可以进行程序实现了。
但是有两个细节需要注意,第一个是dp[i]中的i是前面的i个数字,并不是代表的下标。第二个是有可能数字字符串对应的不同英文字符串数目为0,如字符串“00”,并没有对应的,需要考虑进去这种情况。
public class Solution {
public int numDecodings(String s) {
//如果s为空,s长度为0,s的第一个字符为0,都返回0
if(s == null || s.length() == 0 || s.charAt(0) == '0') return 0;
//由于dp[i]代表前i个字符对应的不同英文字符串的数目,所以需要
//使用到dp[len],就是前len个字符,也就是最终的答案
int len = s.length();
int[] dp = new int[s.length()+1];
//初始化为1,dp[0]=1的原因是dp[2]=dp[0],此时为1,而不是0
dp[0] = 1;
dp[1] = 1;
for(int i = 1; i < len; i++){
//当前的字符为0,但是左边的字符不为1或者2,这是不可能的,因此返回0
if(s.charAt(i) == '0' && !(s.charAt(i-1) == '1' || s.charAt(i-1) == '2')){
return 0;
}
//如果当前为0,则说明一定是10或者是20,因此如下。
//此时为dp[i+1]的原因是,下标i对应的是前面i+1个字符。
if(s.charAt(i) == '0'){
dp[i+1] = dp[i-1];
}
//如果左边的字符为1,当前字符任意
//dp[i-1]代表的是左边字符(i)和当前字符(i+1)组成一个数字,
//dp[i]代表的是,前面i个字符(包括当前字符的左边字符)构成的
//不同字符串的不同字符串,当前字符为单独数字
//如下图所示(https://img-blog.csdn.net/20161029002209631)
else if(s.charAt(i-1) == '1'){
dp[i+1] = dp[i] + dp[i-1];
}
//与上述含义相同,不过有限制
else if(s.charAt(i-1) == '2' && s.charAt(i) <= '6' && s.charAt(i) >= '1'){
dp[i+1] = dp[i] + dp[i-1];
}
//其他的都是确定的一种,所以直接递推
else{
dp[i+1] = dp[i];
}
}
return dp[len];
}
}
图