数字转字母串

  • 题目:规定1和A对应、2和B对应、3和C对应…
    那么一个数字字符串比如"111”就可以转化为:
    “AAA”、“KA"和"AK”
    给定一个只有数字字符组成的字符串str,返回有多少种转化结果
  • 接收信息:index
  • 判断: // 可能性一:i位置的数字转为字母 (因为已经排除0,和i到末尾。所以一定成立)
  • // 可能性二:i和i+1的位置组成一个【1~26】内的数字,转换成字母
  • basecase:当index位置为0时直接说明当前组合无效。不越界时把两位字符转成数字,只有<=26的才有效
    代码
  • 传出信息:i+=1 或 i+=2
// str只含有数字字符0~9,返回多少种转化方案
public static int number(String str) {
   if (str == null || str.length() == 0) {
      return 0;
   }
   return process1(str.toCharArray(), 0);
}

// 【0~i-1】默认已经完成合法转换。只需处理【i~str.length】
public static int process(char[] str, int i) {
//basecase:i到末尾。之前已经完成合法转换。返回1表示这是一种字符串的合法转换序列
   if (i == str.length) {
      return 1;
   }
 // i没到末尾,说明后续还有字符需要合法的转换
     // 0没有对应的字符,说明之前的转换不合法
   if (str[i] == '0') { 
      return 0;
   }
   // str[i] != '0' && i没到末尾
   // 可能性一:i位置的数字转为字母 (因为已经排除0,和i到末尾。所以一定成立)
   int ways = process(str, i + 1);
   // 可能性二:i和i+1的位置组成一个【1~26】内的数字,转换成字母
   if (i + 1 < str.length && (str[i] - '0') * 10 + str[i + 1] - '0' < 27) {
      ways += process(str, i + 2);
   }
   return ways;
}

// 从右往左的动态规划
// 就是上面方法的动态规划版本
// dp[i]表示:str[i,str.length]之间有多少种转化方式
// dp中默认值dp[N]=1(已经排除末尾为0的情况)
// dp[i]只跟dp[i+1]和dp[i+2]有关
public static int dp1(String s) {
   if (s == null || s.length() == 0) {
      return 0;
   }
   char[] str = s.toCharArray();
   int N = str.length;
   int[] dp = new int[N + 1];

   //dp中的默认条件
   dp[N] = 1;
   for (int i = N - 1; i >= 0; i--) {
      if (str[i] != '0') {
         int ways = dp[i + 1];
         if (i + 1 < str.length && (str[i] - '0') * 10 + str[i + 1] - '0' < 27) {
            ways += dp[i + 2];
         }
         dp[i] = ways;
      }
   }
   return dp[0];
}

// 从左往右的动态规划
// dp[i]表示:str[0...i]有多少种转化方式
public static int dp2(String s) {
   if (s == null || s.length() == 0) {
      return 0;
   }
   char[] str = s.toCharArray();
   int N = str.length;
   if (str[0] == '0') {
      return 0;
   }
   int[] dp = new int[N];
   dp[0] = 1;
   for (int i = 1; i < N; i++) {
      if (str[i] == '0') {
         // 如果此时str[i]=='0',那么他是一定要拉前一个字符(i-1的字符)一起拼的,
         // 那么就要求前一个字符,不能也是‘0’,否则拼不了。
         // 前一个字符不是‘0’就够了嘛?不够,还得要求拼完了要么是10,要么是20,如果更大的话,拼不了。
         // 这就够了嘛?还不够,你们拼完了,还得要求str[0...i-2]真的可以被分解!
         // 如果str[0...i-2]都不存在分解方案,那i和i-1拼成了也不行,因为之前的搞定不了。
         if (str[i - 1] == '0' || str[i - 1] > '2' || (i - 2 >= 0 && dp[i - 2] == 0)) {
            return 0;
         } else {
            dp[i] = i - 2 >= 0 ? dp[i - 2] : 1;
         }
      } else {
         dp[i] = dp[i - 1];
         if (str[i - 1] != '0' && (str[i - 1] - '0') * 10 + str[i] - '0' <= 26) {
            dp[i] += i - 2 >= 0 ? dp[i - 2] : 1;
         }
      }
   }
   return dp[N - 1];
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值