描述
有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。
现在给一串数字,返回有多少种可能的译码结果
数据范围:字符串长度满足 0 < n \le 900<n≤90
进阶:空间复杂度 O(n)O(n),时间复杂度 O(n)O(n)
示例1
输入:
"12"
复制返回值:
2
复制说明:
2种可能的译码结果(”ab” 或”l”)
示例2
输入:
"31717126241541717"
复制返回值:
192
复制说明:
192种可能的译码结果
import java.util.*;
public class Solution {
/**
* 解码
* @param nums string字符串 数字串
* @return int整型
*/
public int solve (String nums) {
// write code here
char[] str=nums.toCharArray();
int[] dp=new int[nums.length()];
if(str[0]=='0')
dp[0]=0;
else
dp[0]=1;
if(nums.length()==1){
return dp[0];
}
// System.out.println(dp[0]);
if(str[0]=='1'){
if(str[1]=='0')
dp[1]=1;
else
dp[1]= 2;
}
if(str[0]=='2'){
if(str[1]=='1'||str[1]=='2'||str[1]=='3'||str[1]=='4'||str[1]=='5'||str[1]=='6')
dp[1]= 2;
else
dp[1]= 1;
}
if(str[0]!='1'&&str[0]!='2'&&str[0]!='0'){
dp[1]=1;
}
for(int i=2;i<nums.length();i++){
if(str[i]>='0'&&str[i]<='6'){
// if((str[i-1]=='0'||str[i-1]=='3'||str[i-1]=='4'||str[i-1]=='5'||str[i-1]=='6'||str[i-1]=='7'||str[i-1]=='8'||str[i-1]=='9')&&str[i]=='0')return 0;
if(str[i-1]=='1'||str[i-1]=='2')
{
if(str[i]!='0')
dp[i]=dp[i-1]+dp[i-2];
else
dp[i]=dp[i-1];
}
else{
if(str[i]!='0')
dp[i]=dp[i-1];
else{
return 0;
}
}
}else{
if(str[i-1]=='1')
dp[i]=dp[i-1]+dp[i-2];
else{
dp[i]=dp[i-1];
}
}
}
// System.out.println(dp[nums.length()-2]);
for(int i=0;i<nums.length();i++){
System.out.println(dp[i]);
}
return dp[nums.length()-1];
}
}
标准答案:
import java.util.*;
public class Solution {
public int solve (String nums) {
//排除0
if(nums.equals("0"))
return 0;
//排除只有一种可能的10 和 20
if(nums == "10" || nums == "20")
return 1;
//当0的前面不是1或2时,无法译码,0种
for(int i = 1; i < nums.length(); i++){
if(nums.charAt(i) == '0')
if(nums.charAt(i - 1) != '1' && nums.charAt(i - 1) != '2')
return 0;
}
int[] dp = new int[nums.length() + 1];
//辅助数组初始化为1
Arrays.fill(dp, 1);
for(int i = 2; i <= nums.length(); i++){
//在11-19,21-26之间的情况
if((nums.charAt(i - 2) == '1' && nums.charAt(i - 1) != '0') || (nums.charAt(i - 2) == '2' && nums.charAt(i - 1) > '0' && nums.charAt(i - 1) < '7'))
dp[i] = dp[i - 1] + dp[i - 2];
else
dp[i] = dp[i - 1];
}
return dp[nums.length()];
}
}
思路:
首先想到使用动态规划,dp[i]表示第i个字符位置的可能种类
之后考虑,加上这个字符之后的增加的种类数(这里一定要好好想一下,举例子,看看那些是真的多出来的种类)
最后得出递推公式
在该字符和前一个字符为11-19和21-26的时候dp[i]=dp[i-1]+dp[i-2],其他时候为dp【i-2】
这个做完了之后就写代码
两个注意点:
1. 最好一开始有个预留的比如do【0】是没有意义的表示初值为1,这样比较好,因为递推有i-2所以必须两个初值,如果计算两个有意义的话,很难
2.考虑清楚0的作用有的时候由于0导致整个无意义,而且10和20只有一种可能这两点需要注意。