算法练习帖--4--解码方法(Java)

给定一个只包含数字的非空字符串,请计算解码方法的总数

(题目来源:力扣网)

解码方法:
'A' -> 1 
'B' -> 2 ...
'Z' -> 26 

给定一个只包含数字的非空字符串,请计算解码方法的总数。

示例 1:

输入: "12"
输出: 2
解释: 它可以解码为 "AB"1 2)或者 "L"12)。
示例 2:

分析过程:

1.找到规律(不含特殊情况):

  • 1 位数字 :1种
  • 2 位数字 :1+1种 例:23
  • 3 位数字 : 2+1种 例:666 161 116
  • 4 位数字 :3+2种 例:16 12 1113 1116
  • 5 位数字 :5+3种 例:13214 12115 12011 12213
  • 6 位数字 :8+5种 例:112113
  • n 位数字 :f(n-1)+f(n-2)种
    2. 在上面基础上进一步考虑
    特殊:
    2.1、0开头,连续0,直接返回0次
    2.2、从第二位数字开始遍历字符串
  • 当前数字是0且0之前的数字大于3,直接返回0次。若0之前数字是1或2,绑定两个数字,如果字符串长度为2,返回1,否则当前次数=当前数字的前两位的次数
  • 当前数字不是0
    • 前一位数字为0,该位数字前一位为0,前一位肯定组合了并减去次数,返回上一位数字次数就行
    • 前一位数字不为0且和前一位数字组合大于26,则当前次数=当前前一位数字的次数。 前一位数字不为0且和前一位数字组合小于等于26的话:len=2,返回2,len>2的话:当前次数=当前前一位数字的次数++当前前两位数字的次数。

解决方法

输入: "226"
输出: 3
解释: 它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6)
public static int numDecodings(String s) {
        //以0开头的字符串或两个0连续出现直接返回0,无解
        if(s.charAt(0)=='0'||s.contains("00")) return 0;
        //创建一个存储结果的数组
        int[] m=new int[s.length()];
        m[0]=1;//单独一个不是0的数字(1~9)必合法,第一位次数:0
        for(int i=1;i<s.length();i++){
            if(s.charAt(i)=='0'){//当前数字为0
                if(s.charAt(i-1)>'2') return 0;//0前头不是1,也不是2,无法分开,也无法组合,直接返回0
                else m[i]=i-2<0?1:m[i-2];//10或者20的情况,只能把10,20组合在一起解码
            }else{//当前数字不为0
                if(s.charAt(i-1)=='0') m[i]=m[i-1];//该位数字前一位为0,前一位肯定组合了并减去次数,返回上一级次数就行
                else{//前面数字也不是0
                    //只要满足1...26之间就合法,如“11”可解码成2种
                    if(Integer.parseInt(s.substring(i-1,i+1))<=26) m[i]=(i-2)<0?2:(m[i-1]+m[i-2]);
                    else m[i]=m[i-1];//不合法则返回上一级的次数,因为这个数不能组合,如“138”,只有1种解法
                }
            }
        }
        return m[s.length()-1];
    }

更多解法: 网页跳转

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值