有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。
现在给一串数字,返回有多少种可能的译码结果
数据范围:字符串长度满足
进阶:空间复杂度 ,时间复杂度
有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。
"12"
2
2种可能的译码结果(”ab” 或”l”)
"31717126241541717"
192
192种可能的译码结果
import java.util.*; public class Solution { public int solve (String nums) { int[] dp = new int[nums.length() + 1]; if (nums.equals("0")) return 0; //初始化dp dp[0] = 1; dp[1] = 1; //中间部分 for (int i = 2; i < dp.length; i++) { String str = "" + nums.charAt(i - 2) + nums.charAt(i - 1); if (nums.charAt(i - 1) == '0' && (nums.charAt(i - 2) != '1' && nums.charAt(i - 2) != '2')) { return 0; } if (str == "00") { return 0; } if (str.equals("10") || str.equals("20") || (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 - 2] + dp[i - 1]; } } return dp[dp.length - 1]; } }
import java.util.*; public class Solution { /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * 解码 * @param nums string字符串 数字串 * @return int整型 */ public int solve (String nums) { // write code here // dp[i],分割点在i时返回可能的编码结果数 // 假设分割点在i, dfs(i) = dfs(i - 2)[在i - 2和 i - 1合法时] + dfs(i - 1) //排除0 if(nums.equals("0")) return 0; int len = nums.length(); System.out.print(len); int[] dp = new int[len + 1]; dp[1] = 1; dp[0] = 1; for(int i = 2; i <= len; i++) { int left = 0; int right = 0; if(judge(nums.substring(i - 2, i))) left = dp[i - 2]; if(nums.charAt(i - 1) != '0') right = dp[i - 1]; dp[i] = left + right; } return dp[len]; } private boolean judge(String s) { if(s.charAt(0) == '0') return false; return Integer.valueOf(s) <= 26? true : false; } }
public class Solution { public int solve (String nums) { if(nums.charAt(0) == '0') return 0; int matrix[] = new int[nums.length()]; matrix[0] = 1; for(int i = 1; i < nums.length(); i++) { int value = i == 1 ? 1 : matrix[i-2]; matrix[i] = (nums.charAt(i) == '0' ? 0 : matrix[i-1]) + ( Integer.parseInt(nums.substring(i-1, i+1)) >= 10 && Integer.parseInt(nums.substring(i-1, i+1)) < 27 ? value : 0); if(matrix[i] == 0) return 0; } return matrix[nums.length()-1]; } }
import java.util.*; public class Solution { public int f(String nums,int i){ // 最后一位为0的情况 if((i == nums.length()-1)&&nums.charAt(i)=='0'){ return 0; } else if(i >= nums.length()-1){ // 字符串遍历结束 return 1; } if(nums.charAt(i) == '0'){ return 0; } else if(nums.charAt(i) > '2' || (nums.charAt(i) == '2' && nums.charAt(i+1) > '6')){ return f(nums,i+1); } else{ return f(nums,i+1) + f(nums,i+2); } } public int solve (String nums) { return f(nums,0); } }
import java.util.*; public class Solution { /** 本质是爬楼梯,你想想当前层有多少种到达可能。无非就是看看i-1和i-2这两条路径中,哪一条可行。 */ public int solve (String nums) { // write code here //dp多一位 int[] dp = new int[nums.length()+1]; dp[0] = 0; //处理不同的初始情况,首位为0,则到达位置1的可能为0种,否则为1; if(nums.charAt(0) == '0'){ dp[1] = 0; }else{ dp[1] = 1; } //下面类似爬楼梯数爬法,到达当前的可能性,无法就是i-1和i-2这两种情况,哪条路径走得通。 for(int i = 2; i <= nums.length(); i++){ int method1= 0; int method2= 0; //i-1这条路径 if(nums.charAt(i-1) != '0'){ method1 = dp[i-1]; } //i-2这条路径 if(nums.charAt(i-2)>'0' && nums.charAt(i-2)<='1' || nums.charAt(i-2)>'1' && nums.charAt(i-2)<='2' && nums.charAt(i-1)<='6'){ //由于dp[0]=0, 当测试用例为"10"时,其实method为1。 method2 = dp[i-2] == 0 ? 1 : dp[i-2]; } dp[i] = method1 + method2; } return dp[nums.length()]; } }
public int solve (String nums) { // 1-9 只有一种译码 11-19、21-26 两种译码 (除去10、20) //dp[i],前i个数的译码方法有多少种 //两种译码:直接译码(dp[i]=dp[i-1])和组合译码(dp[i]=dp[i-2]) 所以dp[i]=dp[i-1]+dp[i-2] //一种译码:直接译码(dp[i]=dp[i-1]) 所以dp[i]=dp[i-1] //依次相加,dp[length] if(nums.equals("0")) return 0; if(nums=="10"||nums=="20") return 1; //当0前面,不是1不是2,无法译码,0种 不是10、不是20 则无法译码 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]; Arrays.fill(dp,1);//初始化为1,有1种译码方式 for(int i=2;i<nums.length()+1;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)<'7'&& nums.charAt(i-1)>'0'))){ dp[i]=dp[i-1]+dp[i-2]; }else{ dp[i]=dp[i-1]; } } return dp[nums.length()]; }
public class Solution { public int solve (String nums) { // nums[0,i-1]可以翻译成dp[i]种字符串 int[] dp = new int[nums.length()]; dp[0] = nums.charAt(0) == '0' ? 0 : 1; for (int i = 1; i < dp.length; i++) { if (nums.charAt(i) != '0') { dp[i] = dp[i - 1]; } if (isValid(nums.charAt(i - 1), nums.charAt(i))) { if (i - 2 >= 0) { dp[i] += dp[i - 2]; } else { dp[i]++; } } } return dp[nums.length() - 1]; } private boolean isValid(char c1, char c2) { if (c1 == '0' || c1 >= '3') { return false; } if (c1 == '1') { return c2 >= '0' && c2 <= '9'; } return c2 >= '0' && c2 <= '6'; } }
public int solve (String nums) { int pre1 = 1, pre2 = 0; char[] cs = nums.toCharArray(); for (int i = 0; i < cs.length; i++) { int t = pre1, cont = i == 0 ? 0 : (cs[i - 1] - '0') * 10 + cs[i] - '0'; if (cs[i] == '0') pre1 = 0; if (i != 0 && cont <= 26 && cont >= 10) pre1 += pre2; pre2 = t; } return pre1; }
import java.util.*; public class Solution { public int solve (String nums) { // write code here int n = nums.length(); String s = " " + nums; char[] cs = s.toCharArray(); int[] f = new int[n + 1]; f[0] = 1; for (int i = 1; i < n + 1; i++) { // a : 代表「当前位置」单独形成 item // b : 代表「当前位置」与「前一位置」共同形成 item int a = cs[i] - '0', b = (cs[i - 1] - '0') * 10 + (cs[i] - '0'); // 如果 a 属于有效值,那么 f[i] 可以由 f[i - 1] 转移过来 if (1 <= a && a <= 9) f[i] = f[i - 1]; // 如果 b 属于有效值,那么 f[i] 可以由 f[i - 2] 或者 f[i - 1] & f[i - 2] 转移过来 if (10 <= b && b <= 26) f[i] += f[i - 2]; } return f[n]; } }
public class Solution { public int solve (String nums) { int n = nums.length(); if (nums.charAt(0) == '0') { return 0; } // (时间优化)剪枝,去除无法编码的含0字符串 for (int i = 1; i < n; i++) { if (nums.charAt(i) == '0') { if (nums.charAt(i - 1) == '0' || nums.charAt(i - 1) > '2') return 0; } } // (空间优化)三指针替代DP数组 int ppre = 1; int pre = 1; int cur = 1; for (int i = 1; i < n; i++) { // 等于'0',则说明这个0只能和前一个字符一起编码 // 此处不需要考虑0和前一个字符能否编码,因为无法编码的情况已经提前排除 if (nums.charAt(i) == '0') { cur = ppre; } // 不等于'0',要看和前一个字符能否一起编码 // 能一起编码,则存在两种编码方式,cur=pre+ppre // 不能一起编码,则只有一种编码方式,cur=pre else { int temp = Integer.parseInt(nums.substring(i - 1, i + 1)); if (temp >= 10 && temp <= 26) { cur = pre + ppre; } else { cur = pre; } } ppre = pre; pre = cur; } return cur; } }
public class Solution { /** * 解码 * @param nums string字符串 数字串 * @return int整型 */ public int solve (String nums) { // 如果开头是0,则失败返回0 if(nums.startsWith("0")) return 0; // 获取字符串长度 int size = nums.length(); // dp1保存 当前遍历的i索引减2 的字符翻译次数 // dp2保存 当前遍历的i索引减1 的字符翻译次数 int dp1 = 1, dp2 = 1; for (int i = 1; i <= nums.length(); i++) { int temp = 0; if(nums.charAt(i - 1) != '0') temp = dp2; // temp等于上一个字符的翻译次数 if(i - 2 >= 0){ int num = Integer.parseInt(nums.substring(i - 2, i)); if(num > 9 && num < 27){ // 如果当前字符可以和上一个字符组合成功,那么temp再加上 i-2个字符的翻译次数 temp += dp1; } } // 翻译次数 随着循环不断向右移动 dp1 = dp2; dp2 = temp; } // 最终dp2即为解 return dp2; } }
import java.util.*; public class Solution { /** * 解码 * @param nums string字符串 数字串 * @return int整型 */ public int solve (String nums) { // write code here if(nums.length()==0){ return 0; } if(nums.charAt(0)=='0'){ return 0; } int[] dp = new int[nums.length() + 1]; dp[0] = 1; dp[1] = 1; for (int i = 2; i < nums.length()+1; i++) { if(nums.charAt(i-1)=='0'){ if(i>2 && (nums.charAt(i-2)=='0' || nums.charAt(i-2)>'2')){ return 0; } dp[i] = dp[i-2]; continue; } if (i - 2 >= 0 && nums.charAt(i - 2) > '2') { dp[i] = dp[i - 1]; continue; } if (nums.charAt(i - 1) > '6') { if (i - 2 >= 0 && nums.charAt(i - 2) == '1') { dp[i] = dp[i - 2] + dp[i - 1]; } else { dp[i] = dp[i - 1]; } } else { if (i - 2 >= 0 && (nums.charAt(i - 2) == '2' || nums.charAt(i - 2) == '1')) { dp[i] = dp[i - 2] + dp[i - 1]; } else { dp[i] = dp[i - 1]; } } } return dp[nums.length()]; } }
对原解的优化补足: 解决类似120答案为2的问题public int solve (String nums) { int [] dp = new int[nums.length()+1]; if(nums.length()<1||nums.equals("0")){ return 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; } } Arrays.fill(dp, 1); for(int i=2; i<=nums.length();i++){ 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')){ if(i<nums.length()&&nums.charAt(i)=='0'){ dp[i] = dp[i-2]; }else{ dp[i] = dp[i-1]+dp[i-2]; } }else{ dp[i] = dp[i-1]; } } return dp[nums.length()]; }