问题:
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). 解决:
① 给定一个已经编码过的字符串,判断有几种解码方式。例如:
“12” ---> “AB”,“L”。
“125” ---> “ABE”,“AY”,“LE”
由编码规则可知,编码范围为1 ~ 26,可以知道,一个大写字母可以编码至多两个数字,所以,可以发现,解决方法与climb stairs类似,使用动态规划,假设数组dp[i]表示从头到字符串的第i位,一共有多少种解码方法的话,如果字符串的第i-1位和第i位能组成一个10到26的数字,说明我们是在第i-2位的解码方法上继续解码(dp[i] += dp[i-2])。如果字符串的第i-1位和第i位不能组成有效二位数字,而且第i位不是0的话,说明我们是在第i-1位的解码方法上继续解码(dp[i] += dp[i - 1])。所以,如果两个条件都符合,则dp[i]=dp[i -1]+dp[i + 2],否则dp[i] = dp[i - 1]。
class Solution {//5ms
public int numDecodings(String s) { if(s.length() ==0) return s.length(); int[] dp = new int[s.length() + 1]; dp[0] = 1;//初始化第一种解码方式 dp[1] = s.charAt(0) == '0' ? 0 : 1;//如果第一位是0,则无法解码 for(int i = 2;i <= s.length();i ++){ // 如果字符串的第i-2位和第i-1位能组成一个10到26的数字,说明我们可以在第i-2位的解码方法上继续解码,有两位数字 if(Integer.parseInt(s.substring(i - 2,i)) <= 26 && Integer.parseInt(s.substring(i - 2,i)) >= 10){ dp[i] += dp[i - 2]; } // 如果字符串的第i-2位和第i-1位不能组成有效二位数字,在第i-1位的解码方法上继续解码,只有一位数字 if(Integer.parseInt(s.substring(i-1, i)) != 0){ dp[i] += dp[i - 1]; } } return dp[s.length()]; } }另一种解法:
class Solution { //2ms
public int numDecodings(String s) { if(s == null || s.length() == 0 || (s.length() > 1 && s.charAt(0) == '0')) return 0; int[] dp = new int[s.length() + 1]; dp[0] = 1;//初始化第一种解码方式 for (int i = 1;i < dp.length ;i ++ ) { dp[i] = (s.charAt(i - 1) == '0') ? 0 : dp[i - 1];//在第i-1位的解码方法上继续解码 if(i > 1 && (s.charAt(i - 2) == '1' || (s.charAt(i - 2) == '2') && s.charAt(i - 1) <= '6')){//如果字符串的第i-1位和第i位能组成一个10到26的数字,说明我们可以在第i-2位的解码方法上继续解码 dp[i] += dp[i - 2]; } } return dp[s.length()]; } }② 在discuss中看到的,使用两个变量,分别记录一位数和两位数的情况。
class Solution {//1ms
public int numDecodings(String s){ if (s.length() == 0) return 0; int preFir = 1; int preSec = 1; char[] schar = s.toCharArray(); for (int i = 0;i < schar.length;i ++){ int way = 0; int val1 = schar[i] - '0'; if (val1 >= 1 && val1 <= 9){//1~9之间 way += preFir; } if (i >= 1){//10~26之间 int val2 = (schar[i - 1] - '0') * 10 + val1; if (val2 >= 10 && val2 <= 26){ way += preSec; } } preSec = preFir; preFir = way; } return preFir; } }