LeetCode 之 Decode Ways

原题:

A message containing letters from A-Z is 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.

这个题就是需要注意一些特殊情况,比如100是0,35是1,1010是1;

这个题应该我是用动态规划做的,思路:

1 对字符串的当前字母进行判断,如果是0,没有其他可能,这个decoding的可能性是0

2 如果字符是3-9,说明这个字母起码只能进行单独的解析,而且其可能性和substring(start+1 ,last)的可能性一样多(KEY)

3 如果字符是1或者2,需要考虑较多情况:

    1) 如果进行单独的解析,即把1变成A,2变成B,这种可能性和substring(start+1 ,last)一样多

     2)如果不单独进行解析,即是否和下一位进行两位数的解析(如把11变成K或把12变成L),如果是1,就不需要判断下一个元素了,因为从10到19都可以解析;如果是2,就需要看下一个元素是否是0-6,否则不能进行双位数的解析(即没有27-29),如果可以进行解析,这种可能性和substring(start+2 ,last)一样多(当然,需要判断start+2是否越界),然后把这两种情况加起来就是结果KEY)了,如图1


           图1

4 当前字符向移动位,继续1-3(KEY

5 由于用到了递归,需要判定返回(KEY的情况,其实由于是判断1位数和2位数,有两种返回情况:

    1)字符串只有1位,只要是非0就有一种情况

     2)字符串有2位,情况较多,<1>第一位是0,这个直接返回0 ; <2>第一位是1,如果第2位不是0,就有2种情况(如12);如果第2位是0,就只有一种情况(如10) <3>第1位是2 ,如果第2位是1-6,就有两种情况(如21);如果第2位是从7-9或0,就只有一种情况(如20,27) <4>其他情况返回0(如30),如图2:

6 为了防止超时,需要记录一下,我这里用record[i]代表当从第i个元素开始到string的最后的可能性,其实record[0]就是结果

代码( 376 ms):

public class Solution {
    public int numDecodings(String s) {
        // IMPORTANT: Please reset any member data you declared, as
        // the same Solution instance will be reused for each test case.
       if(s.length()==0) return 0;
        
       int []record = new int[s.length()];
       for (int i = 0 ;i < s.length(); i++){
           record[i] = -1;
       }
       return  numOfSubString(s , 0 , record);
    }
    
    public int numOfSubString(String s , int start , int [] record){
        if(record[start]>=0) return record[start];
        int result = 0;
        if(start>s.length()-1){
            record[start] = 0;
            return 0;
        }
        
        if(s.charAt(start)=='0'){
            record[start] = 0;
            return 0;
        }
        else if(start==s.length()-1 ){
            //判定的是最后一个元素,只要不是0,就是一种情况
            record[start] = 1;
            return 1;
        }
        else if(start==s.length()-2 ){
            //判定的是倒数第二个元素
            if( s.charAt(start)=='1'&& s.charAt(start+1)!='0'  ){
                //11-19都有两种情况
                record[start] = 2;
                return 2;
            }
            else if( s.charAt(start)=='2'&& s.charAt(start+1)>='1'&& s.charAt(start+1)<='6' ){
                //21-26有两种情况
                record[start] = 2;
                return 2;
            }
            else if( s.charAt(start)>='3'&& s.charAt(start+1)=='0') {
                //30,40..90为0种情况
                record[start] = 0;
                return 0;
            }
            //其余的为1种情况,只有10和20
            record[start] = 1;
            return 1;
        }

        if(s.charAt(start) >= '1' ){
            //只要第一个元素不是0,就与substring(start+1,last)的情况数一致
            result = numOfSubString(s , start+1, record);
            
            //与后一个元素可以组成两位数,如10-26,就可以加上这种情况substring(start+2,last)
            if( s.charAt(start) == '1'&& start+1 <= s.length()-1 ){
                result += numOfSubString(s , start+2 ,record);
            }
            else if(s.charAt(start) == '2'  && start+1 <= s.length()-1  && s.charAt(start+1)<='6'){
                result += numOfSubString(s , start+2 ,record);
            }
        }
        record[start] = result;
        return result;
    }
     
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值