【编程题 动态规划】把数字翻译成字符串(详细注释 易懂)

本文解析了一道关于将数字字符串逆向编译回可能的字母字符串的题目,介绍了动态规划方法解决此问题,着重于理解状态转移方程和排除特殊情况下无法组合的编码。通过举例说明,展示了如何利用双重循环实现时间复杂度为O(n)的解码计数。
摘要由CSDN通过智能技术生成

描述

题目描述:把数字翻译成字符串_牛客题霸_牛客网 (nowcoder.com)

有一种将字母编码成数字的方式:'a'->1, 'b->2', ... , 'z->26'。

我们把一个字符串编码成一串数字,再考虑逆向编译成字符串。

由于没有分隔符,数字编码成字母可能有多种编译结果,例如 11 既可以看做是两个 'a' 也可以看做是一个 'k' 。但 10 只可能是 'j' ,因为 0 不能编译成任何结果。

现在给一串数字,返回有多少种可能的译码结果

数据范围:字符串长度满足    0<n≤90

进阶:空间复杂度   O(n),时间复杂度   O(n)

示例1

输入:

"12"

返回值:

2

说明:

2种可能的译码结果(”ab” 或”l”)     

示例2

输入:

"31717126241541717"

返回值:

192

说明:

192种可能的译码结果     

题目解读

     题目说,把一个字符串转成数字,现在让你把数字再转回字符串。 搁着反复横跳呢?! 

但别信它鬼话,如果它给的数字都是字符串转来的,那我转回去,也应该都是字符串,不会出现异常结果,比如 0的前面不是 1 或者 2,导致无法译码,只能直接返回0 

解题思想

    要想时间复杂度O(n)得出结果,还只能用动态规划,用循环,那肯定是双重循环。 动态规划 状态方程好写,但是对于 接触这个思想不多的同学,还是挺难理解的。这个题里面,如果当前数字无法与前面数字组合,比如 当前数字是7,8,9,前一位数字是 2,那它的可能性就是1,或者说 它不能让总的可能性增加。 再比如 前一位数字大于2 或者等于 0 ,那后一位数字无论是多少,都无法与前一位组合(因为这都大于30了,字母最大数字才26)。

      除了上面两种无法与前一位组合的,还有一种是必须与前面组合的,就是当前数字是0,那前一位必须是 1 或者2 ;当然,如果前一位不是1或者2 ,那就直接返回0(用例中有,所以我说它不是从字符串转来的)。  上面三种情况之外,其他情况都是,我可以自己 独当一面,也可以和别人搭伙过日子 。 也就是说,上面三种情况 ,都不会让总的可能性增加,所以 状态方程为 dp[ i ] = dp[ i-1] 。 而这三种情况以外的,可以让总的可能性增加,所以状态方程为 dp[ i ]= dp[ i-1 ]+dp[ i-2 ]  。  

代码注释

    

import java.util.*;


public class Solution {
    /**
     * 解码
     * @param nums string字符串 数字串
     * @return int整型
     */
    public int solve (String nums) {
        // write code here
        int len = nums.length();
      // 如果长度为1,直接返回1,这里默认它不会只给一个0的情况
        if(len ==1)
            return 1;
        int[] dp = new int[len+1];
        dp[0]=1;
        dp[1]=1;
     // 因为三种特殊情况之外的情况,要考虑 dp[i-2]的值,所以从i=2 开始
        for(int i=2;i<= len;i++){
        // dp数组的下标比 nums数组下标 大一位 。 因为第一位的可能性固定,所以从
         // nums数组的第二位开始计算
            if(nums.charAt(i-1) == '0' ){
                if(nums.charAt(i-2)=='1'|| nums.charAt(i-2)=='2')
                     dp[i] = dp[i-1];
                else{
                    dp[i]=0;
                    return 0;
                }
    
            }
           else if(( nums.charAt(i-2)=='2' && nums.charAt(i-1)>'6')
                   ||(nums.charAt(i-2)>'2' || nums.charAt(i-2)=='0'))
                dp[i]= dp[i-1];
            else 
                 dp[i] = dp[i-1]+dp[i-2];
        }
        return dp[len];
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值