题目
规定1和A对应、2和B对应、3和C对应...26和Z对应。
那么一个数字字符串比如"111"就可以转化为:"AAA"、"KA"和"AK"。
给定一个只有数字字符组成的字符串str,返回有多少种转化结果?
思路一:暴力递归
转化的时候要么取一个字符,要么取两个字符。注意:’0‘的情况是没有意义的,如果两个字符时,不能超过26,只有26个字母,最大为Z
//暴力递归法
public static int convertToStringOne(String str){
//边界判断
if(str == null || str.length() == 0){
return 0;
}
//字符串转化为数组
char[] chars = str.toCharArray();
int result = convertOne(chars, 0);
return result;
}
public static int convertOne(char[] chars, int index){
//下标越界直接返回
if(index == chars.length){
return 1;
}
//O做开头是无效解,直接返回
if(chars[index] == '0'){
return 0;
}
//一个字符转的情况
int ans1 = convertOne(chars, index + 1);
int ans2 = ans1;
//两个字符转的情况,第一个字符不大于2,第二个字符不超过7,只有26个字符
if(index + 1 < chars.length && (chars[index] - '0')*10 + (chars[index + 1] - '0') < 27){
ans2 += convertOne(chars, index + 2);
}
return ans2;
}
思路二:傻缓存
用数组存已经计算的结果。
//傻缓存法
public static int convertToStringTwo(String str){
//边界判断
if(str == null || str.length() == 0){
return 0;
}
//字符串转化为数组
char[] chars = str.toCharArray();
int N = chars.length;
//缓存数组
int[] dp = new int[N];
int result = convertTwo(chars, 0, dp);
return result;
}
public static int convertTwo(char[] chars, int index, int[] dp){
//下标越界直接返回
if(index == chars.length){
return 1;
}
if(dp[index] != 0){
return dp[index];
}
//O做开头是无效解,直接返回
if(chars[index] == '0'){
return 0;
}
//一个字符转的情况
int ans1 = convertOne(chars, index + 1);
int ans2 = ans1;
//两个字符转的情况,第一个字符不大于2,第二个字符不超过7,只有26个字符
if(index + 1 < chars.length && (chars[index] - '0')*10 + (chars[index + 1] - '0') < 27){
ans2 += convertOne(chars, index + 2);
}
dp[index] = ans2;
return ans2;
}
思路三:动态规划按规律直接写值
public static int convertToStringThree(String str){
//边界判断
if(str == null || str.length() == 0){
return 0;
}
//字符串转化为数组
char[] chars = str.toCharArray();
int N = chars.length;
//缓存数组
int[] dp = new int[N+1];
//最后一个的情况 相当于 判断:
// if(index == chars.length){
// return 1;
// }
dp[N] = 1;
//填结果
for (int i = N - 1; i >= 0; i--) {
//0 - N-1要判断'0'的情况
if(chars[i] != '0'){
int result = dp[i + 1];
if(i + 1 < chars.length && (chars[i] - '0')*10 + (chars[i + 1] - '0') < 27){
result += dp[i+2];
}
dp[i] = result;
}
}
return dp[0];
}
总结测试
public class ConvertToLetterString {
//暴力递归法
public static int convertToStringOne(String str){
//边界判断
if(str == null || str.length() == 0){
return 0;
}
//字符串转化为数组
char[] chars = str.toCharArray();
int result = convertOne(chars, 0);
return result;
}
public static int convertOne(char[] chars, int index){
//下标越界直接返回
if(index == chars.length){
return 1;
}
//O做开头是无效解,直接返回
if(chars[index] == '0'){
return 0;
}
//一个字符转的情况
int ans1 = convertOne(chars, index + 1);
int ans2 = ans1;
//两个字符转的情况,第一个字符不大于2,第二个字符不超过7,只有26个字符
if(index + 1 < chars.length && (chars[index] - '0')*10 + (chars[index + 1] - '0') < 27){
ans2 += convertOne(chars, index + 2);
}
return ans2;
}
//傻缓存法
public static int convertToStringTwo(String str){
//边界判断
if(str == null || str.length() == 0){
return 0;
}
//字符串转化为数组
char[] chars = str.toCharArray();
int N = chars.length;
//缓存数组
int[] dp = new int[N];
int result = convertTwo(chars, 0, dp);
return result;
}
public static int convertTwo(char[] chars, int index, int[] dp){
//下标越界直接返回
if(index == chars.length){
return 1;
}
if(dp[index] != 0){
return dp[index];
}
//O做开头是无效解,直接返回
if(chars[index] == '0'){
return 0;
}
//一个字符转的情况
int ans1 = convertOne(chars, index + 1);
int ans2 = ans1;
//两个字符转的情况,第一个字符不大于2,第二个字符不超过7,只有26个字符
if(index + 1 < chars.length && (chars[index] - '0')*10 + (chars[index + 1] - '0') < 27){
ans2 += convertOne(chars, index + 2);
}
dp[index] = ans2;
return ans2;
}
public static int convertToStringThree(String str){
//边界判断
if(str == null || str.length() == 0){
return 0;
}
//字符串转化为数组
char[] chars = str.toCharArray();
int N = chars.length;
//缓存数组
int[] dp = new int[N+1];
//最后一个的情况 相当于 判断:
// if(index == chars.length){
// return 1;
// }
dp[N] = 1;
//填结果
for (int i = N - 1; i >= 0; i--) {
//0 - N-1要判断'0'的情况
if(chars[i] != '0'){
int result = dp[i + 1];
if(i + 1 < chars.length && (chars[i] - '0')*10 + (chars[i + 1] - '0') < 27){
result += dp[i+2];
}
dp[i] = result;
}
}
return dp[0];
}
public static String generateStr(int maxSize){
char[] chars = new char[maxSize];
for (int i = 0; i < maxSize; i++) {
int digital = (int)(10 * Math.random());
chars[i] = (char) (digital + '0');
}
return chars.toString();
}
public static void main(String[] args) {
System.out.println("测试开始:");
for (int i = 0; i < 10000; i++) {
//随机生成字符串的大小
int maxSize = (int)(101 * Math.random());
String str = generateStr(maxSize);
int resultOne = convertToStringOne(str);
int resultTwo = convertToStringTwo(str);
int resultThree = convertToStringThree(str);
if(resultOne != resultTwo || resultOne != resultThree || resultTwo != resultThree){
System.out.println("不行,小伙子,再看看!!");
}
}
System.out.println("测试结束");
}
}