有一个消息包含A-Z
通过以下规则编码
'A' -> 1
'B' -> 2
...
'Z' -> 26
现在给你一个加密过后的消息,问有几种解码的方式
样例
给你的消息为12
,有两种方式解码 AB(12) 或者 L(12). 所以返回 2
解题思路:
序列型动态规划。对于序列计数型问题,一般dp[i]代表前i个,而不包括第i个,所以新建dp数组,一般需要多建一个。
最后一步:
一定是一个字母A or B ... or Z。所以最后一步要么是一个数字组成的字母,要么是两个数字组成的字母。
根据最后一步,可推出子问题
子问题:
要求数字串前i个字符的解码方式,就需要知道前i-1和前i-2个字符的解码方式。
确定状态:
设dp[i]为数字串前i个字符的解码方式数
则状态方程:dp[i] = dp[i-1] + dp[i-2]
初始条件与边界条件:
dp[0] = 1
数字串S[i-1]需对应一个字母,即:S[i-1]在[1-9]之间
数字串S[i-2][i-1]组成的两个数字需对应一个字母,即:S[i-2][i-1]在[10-26]之间
public class Solution {
/**
* @param s: a string, encoded message
* @return: an integer, the number of ways decoding
*/
public int numDecodings(String s) {
// write your code here
if(s == null || s.length() == 0)
return 0;
char[] arr = s.toCharArray();
int n = arr.length;
int[] dp = new int[n+1];//dp[i]为数字串前i个字符的解码方式数,不包括i
//初始条件
dp[0] = 1;
if(arr[0] == '0')
dp[1] = 0;
else
dp[1] = 1;
for(int i=2; i<dp.length; i++){
//倒数第一个字符必须为[1,9]之间
if(arr[i-1] == '0')
dp[i-1] = 0;
//倒数两个字符必须在[10-26]之间
String ss = "" + arr[i-2] + arr[i-1];
int temp = Integer.valueOf(ss);
if(temp > 26 || temp == 0)
dp[i-2] = 0;
//状态方程
dp[i] = dp[i-1] + dp[i-2];
}
return dp[n];
}
}