描述
题目描述:把数字翻译成字符串_牛客题霸_牛客网 (nowcoder.com)
有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。
我们把一个字符串编码成一串数字,再考虑逆向编译成字符串。
由于没有分隔符,数字编码成字母可能有多种编译结果,例如 11 既可以看做是两个 'a' 也可以看做是一个 'k' 。但 10 只可能是 'j' ,因为 0 不能编译成任何结果。
现在给一串数字,返回有多少种可能的译码结果
数据范围:字符串长度满足 0<n≤90
进阶:空间复杂度 O(n),时间复杂度 O(n)
示例1
输入:
"12"返回值:
2说明:
2种可能的译码结果(”ab” 或”l”)
示例2
输入:
"31717126241541717"返回值:
192说明:
192种可能的译码结果
题目解读
题目说,把一个字符串转成数字,现在让你把数字再转回字符串。 搁着反复横跳呢?!
但别信它鬼话,如果它给的数字都是字符串转来的,那我转回去,也应该都是字符串,不会出现异常结果,比如 0的前面不是 1 或者 2,导致无法译码,只能直接返回0
解题思想
要想时间复杂度O(n)得出结果,还只能用动态规划,用循环,那肯定是双重循环。 动态规划 状态方程好写,但是对于 接触这个思想不多的同学,还是挺难理解的。这个题里面,如果当前数字无法与前面数字组合,比如 当前数字是7,8,9,前一位数字是 2,那它的可能性就是1,或者说 它不能让总的可能性增加。 再比如 前一位数字大于2 或者等于 0 ,那后一位数字无论是多少,都无法与前一位组合(因为这都大于30了,字母最大数字才26)。
除了上面两种无法与前一位组合的,还有一种是必须与前面组合的,就是当前数字是0,那前一位必须是 1 或者2 ;当然,如果前一位不是1或者2 ,那就直接返回0(用例中有,所以我说它不是从字符串转来的)。 上面三种情况之外,其他情况都是,我可以自己 独当一面,也可以和别人搭伙过日子 。 也就是说,上面三种情况 ,都不会让总的可能性增加,所以 状态方程为 dp[ i ] = dp[ i-1] 。 而这三种情况以外的,可以让总的可能性增加,所以状态方程为 dp[ i ]= dp[ i-1 ]+dp[ i-2 ] 。
代码注释
import java.util.*;
public class Solution {
/**
* 解码
* @param nums string字符串 数字串
* @return int整型
*/
public int solve (String nums) {
// write code here
int len = nums.length();
// 如果长度为1,直接返回1,这里默认它不会只给一个0的情况
if(len ==1)
return 1;
int[] dp = new int[len+1];
dp[0]=1;
dp[1]=1;
// 因为三种特殊情况之外的情况,要考虑 dp[i-2]的值,所以从i=2 开始
for(int i=2;i<= len;i++){
// dp数组的下标比 nums数组下标 大一位 。 因为第一位的可能性固定,所以从
// nums数组的第二位开始计算
if(nums.charAt(i-1) == '0' ){
if(nums.charAt(i-2)=='1'|| nums.charAt(i-2)=='2')
dp[i] = dp[i-1];
else{
dp[i]=0;
return 0;
}
}
else if(( nums.charAt(i-2)=='2' && nums.charAt(i-1)>'6')
||(nums.charAt(i-2)>'2' || nums.charAt(i-2)=='0'))
dp[i]= dp[i-1];
else
dp[i] = dp[i-1]+dp[i-2];
}
return dp[len];
}
}