算法学习之动态规划(leetcode 91 Decode Ways)

leetcode 91. 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.

题意说明,将A-Z 26个英文字母对应成为1-26个数字,当拿到一个英文字符串的时候,很容易将其对应成为一串数字,题目是给出一串数字,然后让你计算出可以转化成为这个数字串的不同英文字符串有多少个。

与王印讨论的思路。
首先,先进行定义,定义dp[i]的含义为,前i个数字能够对应多少个不同的字符,然后进行递推。
列出26个数字,从中发现一些规律。
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26
第一个特殊点,如果当前字符为0,则左边必须为1或者2。
第二个特殊点,如果左边为1,当前字符为1-9,则有两种对应关系。
第三个特殊点,如果左边为2,当前字符为1-6,则有两种对应关系。

根据分析,就可以进行程序实现了。
但是有两个细节需要注意,第一个是dp[i]中的i是前面的i个数字,并不是代表的下标。第二个是有可能数字字符串对应的不同英文字符串数目为0,如字符串“00”,并没有对应的,需要考虑进去这种情况。

public class Solution {
    public int numDecodings(String s) {
        //如果s为空,s长度为0,s的第一个字符为0,都返回0
        if(s == null || s.length() == 0 || s.charAt(0) == '0') return 0;

        //由于dp[i]代表前i个字符对应的不同英文字符串的数目,所以需要
        //使用到dp[len],就是前len个字符,也就是最终的答案
        int len = s.length();
        int[] dp = new int[s.length()+1];    

        //初始化为1,dp[0]=1的原因是dp[2]=dp[0],此时为1,而不是0
        dp[0] = 1;
        dp[1] = 1;

        for(int i = 1; i < len; i++){
            //当前的字符为0,但是左边的字符不为1或者2,这是不可能的,因此返回0
            if(s.charAt(i) == '0' && !(s.charAt(i-1) == '1' || s.charAt(i-1) == '2')){
                return 0;
            }

            //如果当前为0,则说明一定是10或者是20,因此如下。
            //此时为dp[i+1]的原因是,下标i对应的是前面i+1个字符。
            if(s.charAt(i) == '0'){
                dp[i+1] = dp[i-1];
            }
            //如果左边的字符为1,当前字符任意
            //dp[i-1]代表的是左边字符(i)和当前字符(i+1)组成一个数字,
            //dp[i]代表的是,前面i个字符(包括当前字符的左边字符)构成的
            //不同字符串的不同字符串,当前字符为单独数字
            //如下图所示(https://img-blog.csdn.net/20161029002209631)
            else if(s.charAt(i-1) == '1'){
                dp[i+1] = dp[i] + dp[i-1];
            }
            //与上述含义相同,不过有限制
            else if(s.charAt(i-1) == '2' && s.charAt(i) <= '6' && s.charAt(i) >= '1'){
                dp[i+1] = dp[i] + dp[i-1];
            }
            //其他的都是确定的一种,所以直接递推
            else{
                dp[i+1] = dp[i];
            }
        }

        return dp[len];
    }
}


这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值