问题描述:
A message containing letters from A-Z is being encoded to numbers using the following mapping:
‘A’ -> 1
‘B’ -> 2
…
‘Z’ -> 26
Given a non-empty string containing only digits, determine the total number of ways to decode it.
Example 1:
Input: “12”
Output: 2
Explanation: It could be decoded as “AB” (1 2) or “L” (12).
Example 2:
Input: “226”
Output: 3
Explanation: It could be decoded as “BZ” (2 26), “VF” (22 6), or “BBF” (2 2 6).
**解题思路:**动态规划(使用递归会超时)
这题有点像跳台阶,最后面那个字符i可以单独一个,也可以和前面的字符i-1合并到一起,这个有点像最后一个台阶跳一步还是两步。跳一步的话是在DP[i-1]的基础上跳,跳两步的话是在DP[i-2]的基础上跳,因此跳台阶那题的递推公式为DP[i]=DP[i-1]+DP[i-2]。而这题的递归公式也是类似的。
举个栗子:
当前给定的字符串是:“1226”
当前位置:0,则可能的编码为1
当前位置:1,则可能的编码为1-2,12
当前位置:2,则可能的编码为1-2-2,12-2,1-22
当前位置:3,则可能的编码为1-2-2-6,12-2-6,12-26,1-22-6,1-2-26(这里单独一位就是在位置2的基础上加上6,合并就是在位置1的基础上加上26)
解释:若当前在位置1,则当前位置的字符’2’可以选择与前面那个字符合并或者自己单独一位(这就类似于跳两步和跳一步),如果是自己单独一位,那么DP[i]=DP[i-1]。如果是要和前面一位合并,DP[i]=DP[i-2]。若两种情况都是满足的,那么DP[i]=DP[i-1]+DP[i-2]。
在进行DP的时候还需要考虑几种特殊的情况:
(1)当前位置i的字符为’0’,那么不能考虑单独一位,只能考虑合并
(2)当前位置和前面的位置合并的时候>‘26’,那么只能考虑单独一位
代码:
public int DP(String s){
if (s.length()==0){
return 0;
}
/**
* 字符串长度为1的情况
*/
int[] dp=new int[s.length()];
dp[0]=s.charAt(0)=='0'?0:1;
if (s.length()==1){
return dp[0];
}
/**
* 字符串长度为2,第一种是拆分的情况,第二种是合并的情况
*/
dp[1]+=s.charAt(0)>'0' && s.charAt(1)>'0'?1:0;//第一种是独立的情况,有一个为0,就不能拆分了1-0这样子
dp[1]+=(s.charAt(0)=='1'||s.charAt(0)=='2'&&s.charAt(1)<='6'?1:0);//这一种是合并的情况
for (int i=2;i<s.length();i++){
/**
* 当前位置i,能否独立
*/
if (s.charAt(i)!='0'){
dp[i]+=dp[i-1];
}
/**
* 当前位置i,能否合并
*/
if (s.charAt(i-1)=='1' || s.charAt(i-1)=='2'&&s.charAt(i)<='6'){
dp[i]+=dp[i-2];
}
}
return dp[s.length()-1];
}
本文探讨了一种基于数字的解码算法,该算法将字母映射为数字,旨在确定解码给定数字字符串的方法总数。通过动态规划方法解决,避免了递归超时问题,详细解析了算法原理及实现步骤。
1028

被折叠的 条评论
为什么被折叠?



