数字字符串对应解码方式

package leetcode;
/*A message containing letters fromA-Zis 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).

The number of ways decoding"12"is 2.*/
public class Decode_ways {
      public static void main(String[] args) {
        System.out.println(numDecodings("17"));
    }
      
   //我自己的方法是利用简单粗暴的递归,但是那样时间复杂度太高,无法通过,所以利用了记忆化搜索,把子问题的结果进行保存,以免重复计算
      public static int numDecodings(String s) {

           int [] memo =new int[s.length()+1];     //定义数组,存储已解决出来的子问题
           char[] c = s.toCharArray();
           int N = c.length;
           if(N == 0 )                            //字符串长度为0,则直接返回0
               return 0 ;
           memo[0] = numDecodings(c,0,N-1,memo);  //对应方法进行求解
         return memo[0];
          
      }


    private static int numDecodings(char[] c, int i, int n, int[] memo) {
        // TODO Auto-generated method stub
        if(i == n && c[i] == '0')                      //剩下最后一个字符为0,表示这种划分方式有问题,所以返回为0
            return 0;
        if(i >= n )                                    //当已经到结尾了,证明是一种划分方式
            memo[i] = 1;
        if(memo[i] != 0) {                             //当这个子问题已经解决过,则直接返回结果
            return memo[i];
        }
        
        if(c[i]<='0' )                                //字符不符合要求,则此种划分方式有问题,所以返回为0
            memo[i] = 0;
        else if((c[i]=='2' && c[i+1]<='6') || (c[i+1]<='9'&& c[i]=='1')) {    //表示此字符单独为一个,和下一个字符合并在一起都可以
            memo[i] = numDecodings(c, i+1, n, memo) + numDecodings(c, i+2, n, memo); //所以为两种方式的划分结果之和
        }
        else if(c[i]>='1'&& c[i]<='2'&& c[i+1]=='0') {                  //表示若此字符单独划分不可以,只能和下一个字符组合
            memo[i] = numDecodings(c, i+2, n, memo);
        }else {
            memo[i] = numDecodings(c, i+1, n, memo);                   //表示此字符必须单独划分
        }
        return memo[i];         //返回此子问题的结果
    }
}
//以下是牛客网上的最优解法
//成功把自上向下的解决办法,用自下向上来解
/*public int numDecodings(String s) {
    //解题思路:
    //基本是斐波拉契数列dp[i]=dp[i-1]+dp[i-2]
    //dp[i]表示s[0-(i-1)]的解法的个数
    //dp[i-1]表示单独加入新的数字,dp[i-2]表示和前面一个数字凑
    //http://www.cnblogs.com/grandyang/p/4313384.html
    if(s.length() == 0 || s == null || (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++){
            //前面一个字符不是'0'则dp[i]至少等于dp[i-1]
            if(s.charAt(i-1) == '0'){
                dp[i] = 0;
            }else{
                dp[i] = dp[i-1];
            }
            //判断前一个字符和当前字符是不是可以凑
            if(( i > 1 && s.charAt(i-1)<= '6' && s.charAt(i-2) =='2') || ( i > 1 && s.charAt(i-2) == '1' ) ){
                dp[i] += dp[i-2];
            }
    }
     
    return dp[s.length()];*/    //因为dp【0】被占用,所以dp【i】对应就表示i长度的字符串方法

猜你喜欢

转载自blog.csdn.net/ZWB626/article/details/84932041