首页 > 试题广场 >

把数字翻译成字符串

[编程题]把数字翻译成字符串
  • 热度指数:151641 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

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

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

数据范围:字符串长度满足 0 < n \leq 90
进阶:空间复杂度 ,时间复杂度
示例1

输入

"12"

输出

2

说明

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

输入

"31717126241541717"

输出

192

说明

192种可能的译码结果  
import java.util.*;


public class Solution {
    public int solve (String nums) {
        int[] dp = new int[nums.length() + 1];
        if (nums.equals("0")) return 0;
        //初始化dp
        dp[0] = 1;
        dp[1] = 1;
        //中间部分
        for (int i = 2; i < dp.length; i++) {
            String str = "" + nums.charAt(i - 2) + nums.charAt(i - 1);
            if (nums.charAt(i - 1) == '0' && (nums.charAt(i - 2) != '1' &&
                                              nums.charAt(i - 2) != '2')) {
                return 0;
            }
            if (str == "00") {
                return 0;
            }
            if (str.equals("10") || str.equals("20") || (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 - 2] + dp[i - 1];
            }

        }
        return dp[dp.length - 1];
    }
}

编辑于 2024-01-16 21:12:56 回复(0)
import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * 解码
     * @param nums string字符串 数字串
     * @return int整型
     */
    public int solve (String nums) {
        // write code here
        // dp[i],分割点在i时返回可能的编码结果数
        // 假设分割点在i, dfs(i) = dfs(i - 2)[在i - 2和 i - 1合法时] + dfs(i - 1)
        //排除0
        if(nums.equals("0")) 
            return 0;
        int len = nums.length();
        System.out.print(len);
        int[] dp = new int[len + 1];
        dp[1] = 1;
        dp[0] = 1;
        for(int i = 2; i <= len; i++) {
            int left = 0;
            int right = 0;
            if(judge(nums.substring(i - 2, i))) left = dp[i - 2];
            if(nums.charAt(i - 1) != '0') right = dp[i - 1];
            dp[i] = left + right;
        }
        return dp[len];
    }

    private boolean judge(String s) {
        if(s.charAt(0) == '0') return false;
        return Integer.valueOf(s) <= 26? true : false; 
    }
}

编辑于 2024-01-08 18:21:34 回复(0)
public class Solution {
    public int solve (String nums) {
        if(nums.charAt(0) == '0') return 0;
        int matrix[] = new int[nums.length()];
        matrix[0] = 1;
        for(int i = 1; i < nums.length(); i++) {
            int value = i == 1 ? 1 : matrix[i-2];
            matrix[i] = (nums.charAt(i) == '0' ? 0 : matrix[i-1]) + ( Integer.parseInt(nums.substring(i-1, i+1)) >= 10 && Integer.parseInt(nums.substring(i-1, i+1)) < 27 ? value : 0);
            if(matrix[i] == 0) return 0;
        }
        return matrix[nums.length()-1];
    }
}

发表于 2023-10-03 16:13:39 回复(0)
Java遍历:
import java.util.*;
public class Solution {
    public int f(String nums,int i){
        // 最后一位为0的情况
        if((i == nums.length()-1)&&nums.charAt(i)=='0'){
            return 0;
        }
        else if(i >= nums.length()-1){ // 字符串遍历结束
            return 1;
        }
        if(nums.charAt(i) == '0'){
            return 0;
        }
        else if(nums.charAt(i) > '2' || (nums.charAt(i) == '2' && nums.charAt(i+1) > '6')){
            return f(nums,i+1);
        }
        else{
            return f(nums,i+1) + f(nums,i+2);
        }
    }
    public int solve (String nums) {
        return f(nums,0);
    }
}


发表于 2023-08-25 21:44:03 回复(0)
import java.util.*;


public class Solution {
    /**
        本质是爬楼梯,你想想当前层有多少种到达可能。无非就是看看i-1和i-2这两条路径中,哪一条可行。
     */
    public int solve (String nums) {
        // write code here
        //dp多一位
        int[] dp = new int[nums.length()+1];
        dp[0] = 0;
        //处理不同的初始情况,首位为0,则到达位置1的可能为0种,否则为1;
        if(nums.charAt(0) == '0'){
            dp[1] = 0;
        }else{
            dp[1] = 1;
        }
        //下面类似爬楼梯数爬法,到达当前的可能性,无法就是i-1和i-2这两种情况,哪条路径走得通。
        for(int i = 2; i <= nums.length(); i++){
            int method1= 0;
            int method2= 0;
            //i-1这条路径
            if(nums.charAt(i-1) != '0'){
                method1 = dp[i-1];
            }
            //i-2这条路径
            if(nums.charAt(i-2)>'0' && nums.charAt(i-2)<='1' 
                || nums.charAt(i-2)>'1' && nums.charAt(i-2)<='2' && nums.charAt(i-1)<='6'){
                //由于dp[0]=0, 当测试用例为"10"时,其实method为1。
                method2 = dp[i-2] == 0 ? 1 : dp[i-2];
            }

            dp[i] = method1 + method2;            
        }
        return dp[nums.length()];
    }
}

发表于 2023-08-11 16:24:21 回复(0)
public int solve (String nums) {
        // 1-9  只有一种译码    11-19、21-26  两种译码  (除去10、20)
        //dp[i],前i个数的译码方法有多少种
        //两种译码:直接译码(dp[i]=dp[i-1])和组合译码(dp[i]=dp[i-2])  所以dp[i]=dp[i-1]+dp[i-2]
        //一种译码:直接译码(dp[i]=dp[i-1])  所以dp[i]=dp[i-1]
        //依次相加,dp[length]
        if(nums.equals("0")) return 0;
        if(nums=="10"||nums=="20") return 1;
        //当0前面,不是1不是2,无法译码,0种   不是10、不是20  则无法译码
        for(int i=1;i<nums.length();i++){
            if(nums.charAt(i)=='0'){
                if(nums.charAt(i-1)!='1'&&nums.charAt(i-1)!='2'){
                    return 0;
                }
            }
        }
        //
        int[] dp=new int[nums.length()+1];
        Arrays.fill(dp,1);//初始化为1,有1种译码方式
        for(int i=2;i<nums.length()+1;i++){
            //11-19 21-26
            if(((nums.charAt(i-2)=='1'&&nums.charAt(i-1)!='0')||(nums.charAt(i-2)=='2'&&nums.charAt(i-1)<'7'&& nums.charAt(i-1)>'0'))){
                dp[i]=dp[i-1]+dp[i-2];
            }else{
                dp[i]=dp[i-1];
            }
        }
        return dp[nums.length()];
 
    }

发表于 2023-07-23 11:32:30 回复(0)
public class Solution {
    public int solve (String nums) {
        // nums[0,i-1]可以翻译成dp[i]种字符串
        int[] dp = new int[nums.length()];
        dp[0] = nums.charAt(0) == '0' ? 0 : 1;
        for (int i = 1; i < dp.length; i++) {
            if (nums.charAt(i) != '0') {
                dp[i] = dp[i - 1];
            }
            if (isValid(nums.charAt(i - 1), nums.charAt(i))) {
                if (i - 2 >= 0) {
                    dp[i] += dp[i - 2];
                } else {
                    dp[i]++;
                }
            }
        }
        return dp[nums.length() - 1];
    }
    private boolean isValid(char c1, char c2) {
        if (c1 == '0' || c1 >= '3') {
            return false;
        }
        if (c1 == '1') {
            return c2 >= '0' && c2 <= '9';
        }
        return c2 >= '0' && c2 <= '6';
    }
}

发表于 2023-05-31 11:06:33 回复(0)
import java.util.*;

public class Solution {
    /**
     * 解码
     * @param nums string字符串 数字串
     * @return int整型
     */
    public int solve (String nums) {
        // write code here

        //排除0
        if (nums.equals("0"))
            return 0;
        //排除只有一种可能的10 和 20
        if (nums == "10" || nums == "20")
            return 1;
        //当0的前面不是1或2时,无法译码,0种
       
        int[] dp = new int[nums.length() + 1];
        //int dp1 = 1;
        //int dp2 = 1;
        dp[0]=1;
        dp[1]=1;
        for (int i = 2; i <= nums.length(); i++) {
            //int temp = 0;
            if (nums.charAt(i-1) == '0')
                if (nums.charAt(i - 2) != '1' && nums.charAt(i - 2) != '2')
                    return 0;
            if ((nums.charAt(i - 2) == '1' && nums.charAt(i - 1) != '0') ||
                    (nums.charAt(i - 2) == '2' && nums.charAt(i - 1) > '0' &&
                     nums.charAt(i - 1) < '7')) {
                dp[i] = dp[i - 1] + dp[i - 2];

            } else {
                dp[i] = dp[i - 1];
            }
        }
        return dp[nums.length()];
    }
}
发表于 2023-03-20 20:07:37 回复(0)
    public int solve (String nums) {
        int pre1 = 1, pre2 = 0;
        char[] cs = nums.toCharArray();
        for (int i = 0; i < cs.length; i++) {
            int t = pre1, cont = i == 0 ? 0 : (cs[i - 1] - '0') * 10 + cs[i] - '0';
            if (cs[i] == '0') pre1 = 0;
            if (i != 0 && cont <= 26 && cont >= 10) pre1 += pre2;
            pre2 = t;
        }
        return pre1;
    }

发表于 2023-02-08 18:00:58 回复(1)
import java.util.*;


public class Solution {
    public int solve (String nums) {
        // write code here
        int n = nums.length();
        String s = " " + nums;
        char[] cs = s.toCharArray();
        int[] f = new int[n + 1];
        f[0] = 1;
        for (int i = 1; i < n + 1; i++) { 
            // a : 代表「当前位置」单独形成 item
            // b : 代表「当前位置」与「前一位置」共同形成 item
            int a = cs[i] - '0', b = (cs[i - 1] - '0') * 10 + (cs[i] - '0');
            // 如果 a 属于有效值,那么 f[i] 可以由 f[i - 1] 转移过来
            if (1 <= a && a <= 9) f[i] = f[i - 1];
            // 如果 b 属于有效值,那么 f[i] 可以由 f[i - 2] 或者 f[i - 1] & f[i - 2] 转移过来
            if (10 <= b && b <= 26) f[i] += f[i - 2];
        }
        return f[n];
    }
}

发表于 2023-01-24 13:53:52 回复(2)
public class Solution {
    public int solve (String nums) {
        int n = nums.length();

        if (nums.charAt(0) == '0') {
            return 0;
        }
        // (时间优化)剪枝,去除无法编码的含0字符串
        for (int i = 1; i < n; i++) {
            if (nums.charAt(i) == '0') {
                if (nums.charAt(i - 1) == '0' || nums.charAt(i - 1) > '2')
                    return 0;
            }
        }

        // (空间优化)三指针替代DP数组
        int ppre = 1;
        int pre = 1;
        int cur = 1;
        for (int i = 1; i < n; i++) {
            // 等于'0',则说明这个0只能和前一个字符一起编码
            // 此处不需要考虑0和前一个字符能否编码,因为无法编码的情况已经提前排除
            if (nums.charAt(i) == '0') {
                cur = ppre;
            } 
            // 不等于'0',要看和前一个字符能否一起编码
            // 能一起编码,则存在两种编码方式,cur=pre+ppre
            // 不能一起编码,则只有一种编码方式,cur=pre
            else {
                int temp = Integer.parseInt(nums.substring(i - 1, i + 1));
                if (temp >= 10 && temp <= 26) {
                    cur = pre + ppre;
                } else {
                    cur = pre;
                }
            }
            ppre = pre;
            pre = cur;
        }
        return cur;
    }
}

发表于 2022-12-12 23:57:09 回复(0)
使用两个变量 dp1,dp2 :
       dp1保存当前遍历字符索引 - 2的位置时共有多少种翻译组合
       dp2保存当前遍历字符索引 - 1的位置时共有多少种翻译组合      
这两个变量不断随着循环向右移动,最终循环结束,dp2 即为解
public class Solution {
    /**
     * 解码
     * @param nums string字符串 数字串
     * @return int整型
     */
    public int solve (String nums) {
        // 如果开头是0,则失败返回0
        if(nums.startsWith("0")) return 0;
        // 获取字符串长度
        int size = nums.length();

        // dp1保存 当前遍历的i索引减2 的字符翻译次数
        // dp2保存 当前遍历的i索引减1 的字符翻译次数
        int dp1 = 1, dp2 = 1;
        for (int i = 1; i <= nums.length(); i++) {
            int temp = 0;
            if(nums.charAt(i - 1) != '0') temp = dp2; // temp等于上一个字符的翻译次数


            if(i - 2 >= 0){
                int num = Integer.parseInt(nums.substring(i - 2, i));
                if(num > 9 && num < 27){ // 如果当前字符可以和上一个字符组合成功,那么temp再加上 i-2个字符的翻译次数
                    temp += dp1;
                }
            }
            // 翻译次数 随着循环不断向右移动
            dp1 = dp2;
            dp2 = temp;
        }
        // 最终dp2即为解
        return dp2;
    }

}



发表于 2022-11-23 12:41:29 回复(0)
有一说一,牛客你能不能告诉我,异常情况我应该给你如何返回?返回-1还是0?每次都要提交测一下异常数据的返回。。。
import java.util.*;


public class Solution {
    /**
     * 解码
     * @param nums string字符串 数字串
     * @return int整型
     */
    public int solve (String nums) {
        // write code here
        if(nums.length()==0){
            return 0;
        }
        if(nums.charAt(0)=='0'){
            return 0;
        }
        int[] dp = new int[nums.length() + 1];
        dp[0] = 1;
        dp[1] = 1;
        for (int i = 2; i < nums.length()+1; i++) {
            if(nums.charAt(i-1)=='0'){
                if(i>2 && (nums.charAt(i-2)=='0' || nums.charAt(i-2)>'2')){
                    return 0;
                }
                dp[i] = dp[i-2];
                continue;
            }
            if (i - 2 >= 0 && nums.charAt(i - 2) > '2') {
                dp[i] = dp[i - 1];
                continue;
            }
            if (nums.charAt(i - 1) > '6') {
                if (i - 2 >= 0 && nums.charAt(i - 2) == '1') {
                    dp[i] = dp[i - 2] + dp[i - 1];
                } else {
                    dp[i] = dp[i - 1];
                }
            } else {
                if (i - 2 >= 0 && (nums.charAt(i - 2) == '2' || nums.charAt(i - 2) == '1')) {
                    dp[i] = dp[i - 2] + dp[i - 1];
                } else {
                    dp[i] = dp[i - 1];
                }
            }
        }
        return dp[nums.length()];
    }
}


发表于 2022-11-07 21:54:25 回复(0)
对原解的优化补足: 解决类似120答案为2的问题
    public int solve (String nums) {
        int [] dp = new int[nums.length()+1];
        if(nums.length()<1||nums.equals("0")){
            return 0;
        }
        for(int i=1; i<nums.length();i++){
            if(nums.charAt(i)=='0'){
                if((nums.charAt(i-1)!='1')&&(nums.charAt(i-1)!='2'))
                    return 0;
            }
        }
        Arrays.fill(dp, 1);
        for(int i=2; i<=nums.length();i++){
            if((nums.charAt(i-2)=='1'&&nums.charAt(i-1)>'0')||
            (nums.charAt(i-2)=='2'&&nums.charAt(i-1)>'0'&&nums.charAt(i-1)<'7')){
                if(i<nums.length()&&nums.charAt(i)=='0'){
                    dp[i] = dp[i-2];
                }else{
                    dp[i] = dp[i-1]+dp[i-2];
                } 
            }else{
                dp[i] = dp[i-1];
            }
        }
        return dp[nums.length()];
    }

发表于 2022-09-28 17:53:45 回复(0)
这道题主要考虑对0的处理,使用动态规划申请一个dp一维数组,dp[i]的含义是,从头开始到第i个字符的有几种译码方式;对第一个和第二个字符特殊处理,从i=2开始,判断nums.charAt[i]是否为0,如果为0,要判断nums.charAt[i-1]和nums.charAt(i) 是否能组成编码,不能则返回0,能则返回 dp[i] = dp[i - 2],即把后面看作一个整体,编码结果跟这个整体的前面部分是一样的;如果不为0,判断(nums.charAt(i - 1)==1,2和不等于1和2的情况即可,代码如下:
import java.util.*;

public class Solution {
    /**
     * 解码
     * @param nums string字符串 数字串
     * @return int整型
     */
    public int solve (String nums) {
        // write code here
        if (nums.length() == 0) {
            return 0;
        }

        int n = nums.length();
        int []dp = new int[n];

        //讨论第一个字符为0的情况
        if (nums.charAt(0) == '0') {
            return 0;
        } else   dp[0] = 1;

        System.out.print(dp[0]);
        if (nums.length() >= 2) {
        
            //当i为0
            if (nums.charAt(1) - '0' == 0) {
                if (nums.charAt(0) - '0' == 0 || nums.charAt(0) - '0' > 2) {
                    return 0;
                }
                //如果i-1为1或者2时
                if ((nums.charAt(0) - '0' > 0 && nums.charAt(0) - '0' <= 2)) {
                    dp[1] = dp[0];
                }
            }
            //当i不为0
            else {
                if (nums.charAt(0) - '0' == 1) {
                        dp[1] = 2;
                    }
                    if (nums.charAt(0) - '0' == 2) {
                        if (nums.charAt(1) - '0' <= 6) {
                            dp[1] = 2;
                        } else dp[1] = 1;
                    }
                    if (nums.charAt(0) - '0' > 2) {
                        dp[1] = 1;
                    }
            }
        }
        
        if (nums.length() > 2) {
            for (int i = 2; i < n; i++) {
                //当i为0
                if (nums.charAt(i) - '0' == 0) {
                    //如果i-1为0或者大于2时,返回0
                    if (nums.charAt(i - 1) - '0' == 0 || nums.charAt(i - 1) - '0' > 2) {
                        return 0;
                    }
                    //如果i-1为1或者2时
                    if ((nums.charAt(i - 1) - '0' > 0 && nums.charAt(i - 1) - '0' <= 2)) {
                        dp[i] = dp[i - 2];
                    }
                }
                //当i不为0
                else {
                    if (nums.charAt(i - 1) - '0' == 1) {
                        dp[i] = dp[i - 1] + dp[i - 2];
                    }
                    if (nums.charAt(i - 1) - '0' == 2) {
                        if (nums.charAt(i) - '0' <= 6) {
                            dp[i] = dp[i - 1] + dp[i - 2];
                        } else dp[i] = dp[i - 1];
                    }
                    if (nums.charAt(i - 1) - '0' > 2||nums.charAt(i - 1) - '0'==0) {
                        dp[i] = dp[i - 1];
                    }
                }
                
            }
        }
        
        return dp[n - 1];
    }
}

发表于 2022-09-28 13:20:58 回复(0)

问题信息

上传者:牛客332641号
难度:
55条回答 4925浏览

热门推荐

通过挑战的用户

查看代码