解码方法

给定一个只包含数字的字符串s,计算按照特定规则解码它的方法数。使用动态规划算法,根据字符串的每个字符及其组合判断解码方式,递归地计算解码方法数。例如,输入s='112',解码方法数为3。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Decode Ways

A message containing letters from A-Z can be encoded into numbers using the following mapping:

​ ‘A’ -> “1”

​ ‘B’ -> “2”

​ …

​ ‘Z’ -> “26”

To decode the encoded message, all the digits must be grouped then mapped back into letters using the reverse of the mapping above (there may be multiple ways). For example, “11106” can be mapped into:

  • “AAJF” with the grouping (1, 1, 10, 6)
  • “KJF” with the grouping (11, 10, 6)

Note that the grouping (1, 11, 06) is invalid because “06” cannot be mapped into ‘F’ since “6” is different from “06”.

Given a string s containing only digits, return the number of ways to decode it.

The answer is guaranteed to fit in a 32-bit integer.

Example 1:

Input: s = “12”

Output: 2

Explanation: “12” could be decoded as “AB”(1, 2) or “L”(12).

Example 2:

Input: s = “226”

Output: 3

Explanation: “226” could be decoded as “BZ”(2, 26), “VF”(22, 6), or “BBF”(2, 2, 6).

Example 3:

Input: s = “0”

Output: 0

Explanation: There is no character that is mapped to a number starting with 0.

The only valid mappings with 0 are ‘J’ -> “10” and ‘T’ -> “20”, neither of which start with 0.

Hance, there are no valid ways to decode this since all digits need to be mapped.

Example 4:

Input: s = “06”

Output: 0

Explanation: “06” cannot be mapped to “F” because of the leading zero (“6” is different from “06”).

Constraints:

  • 1 <= s.length <= 100
  • s contains only digits and may contain leading zero(s).

今天的每日一题是这样的:一个由大写字母组成的字符串可以编码为一个纯数字串,编码规则是这样的:A编码为1,B编码为2,……Z编码为26.但是编码后的串里每个字符之间是没有分隔符的,也就是说26我们可以解码为Z也可以解码为B(2)F(6)。这样的话一个编码串就可能会有多种解码方式。题目要求是给我们输入一个编码串,让我们计算这个串可以用几种不同的方式解码,输出解码方法数。

这道题可以使用动态规划算法来实现。

用f(n)表示s的前n个字符组成的串的解码方法数,设len为s的长度,那么显然,f(len)即是我们所要求的结果。

而考虑下面的情况:

当串的长度为n时,设字符串里的字符分别为i1,i2,… in

在这里插入图片描述

此时,我们可能会用到的解码方法有两种:

  • 如果i n不为0,那么我们可以认为i n是一个字符,把它解码为一个字母,这种情况下f(n) 就等于f(n-1)
  • 如果i n-1 不为0,并且i n-1与i n组成的数字小于等于26,那么就可以认为i n-1,i n组合起来为一个字符,把它们两个解码为一个字母,这种情况下f(n)等于f(n-2)

这两种情况的和即为f(n)的值。

并且,我们可以很容易得到,在字符串没有前导0的情况下,f(1) =1,f(0)=1(因为空串可以解码为空串,也是一种解码方式,所以空串的结果不是0而是1)。

我再举一个例子,深入理解一下这个思想:

如输入串为:“112”

在这里插入图片描述

  • f(1): 即“1”的解码方法数,显然它只能解码为“A”,结果为1

在这里插入图片描述

  • f(2): 此时的编码串为"11",用刚才的两种情况来判断:

    • 字符串的最后一位是‘1’ != ‘0’,所以把1解码为A,这种情况下,f(2) = f(1) = 1
      在这里插入图片描述

    • 字符串的最后两位是“11”,满足上述的第二个条件,所以可以把11解码为K,这种情况下,f(2) += f(0) = 1+1 = 2

在这里插入图片描述

所以f(2) = 2

  • f(3):此时的编码串为“112”

    • 最后一位’2’ != ‘0’,所以将2编码为B,而在’2’之前的“11”,就是上面的f(2),所以f(3) += f(2)

在这里插入图片描述

  • 最后两位“12”,满足条件,可以解码为L,所以将12解码为L,前面的”1“则按照f(1)来计算,那么f(3) += f(1)

在这里插入图片描述

综上,f(3) = f(1) + f(2) = 3

所以,“112”的解码方式有3种

长度为4、5或者更长的串也是根据这个思想来计算,思路是一样的,这里就不再赘述,按照这个思想,写出的代码如下:

/**
 * @author: LittleWang
 * @date: 2021/4/21
 * @description:
 */
public class Solution {
    public int numDecodings(String s) {
        if(s.charAt(0) == '0') {        //如果编码串有前导0,那么是一定没有办法解码的,直接返回0
            return 0;
        }
        int len = s.length();
        int[] f = new int[len+1];     //用f[n]来存放字符串的前n个字符组成的串可以解码的个数,因为数组下标是从0开始的,为了直观,我们让数组的长度为len+1
        f[0] = 1;       //当长度为0,即s为空串时,可以解码为一个空串,所以解码方法有1种,不是0.
        for (int i = 1; i <= len; i++) {
            if(s.charAt(i-1) != '0') {
                f[i] += f[i-1];
            }
            if(i > 1 && 10*(s.charAt(i-2)-'0')+(s.charAt(i-1)-'0') <= 26 && s.charAt(i-2) != '0') {
                f[i] += f[i-2];
            }
        }

        return f[len];
    }
}

提交结果:

在这里插入图片描述

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值