解码方法数问题

解码,方法,问题 · 浏览次数 : 223

小编点评

**暴力递归解法** **算法描述** 该算法使用暴力递归来枚举所有可能的解码方法。对于每个位置 i,该算法尝试以下三种决策: - 如果 str[i] == '0',则该位置无法解码。 - 如果 str[i] == '1',则可以解码成一个字符。 - 如果 str[i] == '2',则可以解码成两个字符,但只有当 i + 1 和 i + 2 之间的字符是 '1' 时才能进行解码。 **动态规划解法** **算法描述** 该算法使用动态规划来计算所有可能的解码方法的数量。对于每个位置 i,该算法记录以下三个值: - dp[i] 表示从 i 一直到最后,解码数量是多少。 - dp[i] = 1 表示在该位置可以解码成一个字符。 - dp[i] = dp[i + 1] 表示在该位置可以解码成两个字符。 - dp[i] = dp[i + 2] 表示在该位置可以解码成三个字符,但只有当 i + 1 和 i + 2 之间的字符是 '1' 时才能进行解码。 **时间复杂性** 暴力递归解法的时间复杂性为 O(n),其中 n 是字符串长度。 动态规划解法的时间复杂性为 O(n),其中 n 是字符串长度。

正文

解码方法数问题

作者:Grey

原文地址:

博客园:解码方法数问题

CSDN:解码方法数问题

题目描述

一条包含字母 A-Z 的消息通过以下映射进行了 编码 :

'A' -> 1
'B' -> 2
...
'Z' -> 26

要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可能有多种方法)。例如,"11106" 可以映射为:

"AAJF" ,将消息分组为 (1 1 10 6)
"KJF" ,将消息分组为 (11 10 6)
注意,消息不能分组为  (1 11 06) ,因为 "06" 不能映射为 "F" ,这是由于 "6" 和 "06" 在映射中并不等价。

给你一个只含数字的 非空 字符串 s ,请计算并返回 解码 方法的 总数 。

题目数据保证答案肯定是一个 32 位 的整数。

示例 1:

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

输入:s = "226"
输出:3
解释:它可以解码为 "BZ" (2 26), "VF" (22 6), 或者 "BBF" (2 2 6) 。
示例 3:

输入:s = "0"
输出:0
解释:没有字符映射到以 0 开头的数字。
含有 0 的有效映射是 'J' -> "10" 和 'T'-> "20" 。
由于没有字符,因此没有有效的方法对此进行解码,因为所有数字都需要映射。
示例 4:

输入:s = "06"
输出:0
解释:"06" 不能映射到 "F" ,因为字符串含有前导 0("6" 和 "06" 在映射中并不等价)。

题目链接:LeetCode 91. Decode Ways

暴力递归解

定义递归函数int process(int i, char[] str)

递归含义表示:从 i 一直到最后,得到的解码方法数有多少

base case 是:

当 i 已经大于 str.length,说明之前的解码决策有问题,直接返回 0。

当 i 正好等于 str.length, 说明之前的决策正好有一种符合条件的情况,返回 1。

接下来就是普遍情况,即:i 小于 str.length, 此时,有如下几种决策情况

第一种情况

str[i]=='0',由于 0 无法解码成任何字符,也无法和后一个进行拼凑成一个字符的编码,所以,直接返回 0。表示决策无效。

第二种情况

str[i] == '1', 则可以有如下决策,首先,str[i]位置独立编码成一个字符,或者str[i]str[i+1]结合解码成一个字符。

第三种情况

str[i] == '2', 则可以有如下决策,首先,str[i]位置独立编码成一个字符,或者str[i]str[i+1]结合解码成一个字符,但是此时的str[i+1]的字符有条件,即:

i + 1 < str.length && str[i + 1] <= '6'

只有满足这个条件,str[i]才能和str[i+1]结合解码成一个字符。

第四种情况
str[i] > '2', 则str[i]只能单独解码成一个字符。

暴力解法的完整代码如下

class Solution {
    public static int numDecodings(String s) {
        if (null == s || s.length() < 1) {
            return 0;
        }
        char[] str = s.toCharArray();
        return process(0, str);

    }

    // 从i一直到最后,得到的解码数
    public static int process(int i, char[] str) {
        if (i > str.length) {
            return 0;
        }
        if (i == str.length) {
            return 1;
        }
        // i < str.length
        if (str[i] == '0') {
            return 0;
        }
        if (str[i] == '1') {
            int p1 = process(i + 1, str);
            int p2 = process(i + 2, str);
            return p1 + p2;
        }
        if (str[i] == '2') {
            int p1 = process(i + 1, str);
            if (i + 1 < str.length && str[i + 1] <= '6') {
                p1 += process(i + 2, str);
            }
            return p1;
        }
        return process(i + 1, str);
    }
}

直接超时

image

动态规划

有了上述暴力递归解法,可以直接改成动态规划解法,由于递归函数只有一个可变参数,所以定义一个一维数组即可装下所有可能性。

int[] dp = new int[str.length + 1];

dp[i]的含义和递归函数process(i,str)的含义一样,都是从 i 开始到最后,解码数量是多少。

由于暴力递归方法中,process(i,str)依赖process(i+1,str)process(i+2,str)

所以对于 dp 数组来说, dp[i]的值依赖dp[i+1]dp[i+2]决策的结果,

根据暴力递归方法中的 base case,可以得到 dp 的某些行列的初始值,然后根据递推公式进行递归,最后返回dp[0]就是结果。

动态规划解的完整代码如下

class Solution {
    public static int numDecodings(String s) {
        if (null == s || s.length() < 1) {
            return 0;
        }
        char[] str = s.toCharArray();
        int[] dp = new int[str.length + 1];
        dp[str.length] = 1;
        for (int i = str.length - 1; i >= 0; i--) {
            if (str[i] == '0') {
                dp[i] = 0;
            } else {
                dp[i] = dp[i + 1];
                if (str[i] == '1' && i + 1 < str.length) {
                    dp[i] = dp[i] + dp[i + 2];
                } else if (str[i] == '2' && i + 1 < str.length && str[i + 1] <= '6') {
                    dp[i] += dp[i + 2];
                }
            }
        }
        return dp[0];
    }
}

更多

算法和数据结构笔记

与解码方法数问题相似的内容:

解码方法数问题

解码方法数问题 作者:Grey 原文地址: 博客园:解码方法数问题 CSDN:解码方法数问题 题目描述 一条包含字母 A-Z 的消息通过以下映射进行了 编码 : 'A' -> 1 'B' -> 2 ... 'Z' -> 26 要 解码 已编码的消息,所有数字必须基于上述映射的方法,反向映射回字母(可

昇腾实战丨DVPP媒体数据处理视频解码问题案例

摘要:本期就分享几个关于DVPP视频解码问题的典型案例,并给出原因分析及解决方法 本文分享自华为云社区《DVPP媒体数据处理视频解码问题案例》,作者:昇腾CANN 。 DVPP(Digital Vision Pre-Processing)是昇腾AI处理器内置的图像处理单元,通过AscendCL媒体数

[转帖]针对容器的nginx优化

针对容器的nginx优化 本篇文章介绍了 Nginx 在容器内使用遇到的CPU核数获取问题以及对应的解决方法。 回顾上篇文章:TCP 半连接队列和全连接队列 背景 容器技术越来越普遍,很多公司已经将容器技术作为基础架构的一部分,容器中可以运行任何软件,包括 Web Server、Applicatio

【数仓运维实践】关于GaussDB(DWS)单SQL磁盘空间管控

摘要:本文主要讲解数仓运维中遇到单SQL磁盘空间管控问题的解析和方案。 本文分享自华为云社区《GaussDB(DWS)运维 -- 单SQL磁盘空间管控》,作者: 譡里个檔。 【问题描述】 执行部分SQL语句时出现如下报错信息(具体数值可能因为配置有差异),本文针对根因和场景触发场景,确定触发此类问题

现代数据平台要实现自助用数,要解决的三个问题

摘要:华为云FusionInsight MRS HetuEngine持续提升自助用数分析平台的可服务、易运维能力,基于AI技术持续提升对数据分析平台的智能化赋能水平,引领现代数据分析平台向专业化、智能化、易运维、高性能方向演进。 本文分享自华为云社区《现代数据平台要实现自助用数还要解决的三大问题》,

昇腾实战丨DVPP媒体数据处理图片解码问题案例

摘要:本期就分享几个关于DVPP图片解码问题的典型案例,并给出原因分析及解决方法。 本文分享自华为云社区《DVPP媒体数据处理图片解码问题案例》,作者:昇腾CANN 。 DVPP(Digital Vision Pre-Processing)是昇腾AI处理器内置的图像处理单元,通过AscendCL媒体

[转帖]查看docker中运行的JVM参数问题及解决方法

方法一、jcmd命令: 1、jps获取java的线程id 2、jcmd pidVM.flags获取 51152:-XX:CICompilerCount=3 -XX:InitialHeapSize=526385152 -XX:MaxHeapSize=1073741824 -XX:MaxNewSize=

[转帖]Java实战之OutOfMemoryError异常问题及解决方法

https://www.jb51.net/article/244872.htm + 目录 在Java虚拟机规范的描述中,除了程序计数器外,虚拟机内存的其他几个运行时区域都有发生OutOfMemoryError (下文称OOM)异常的可能。本篇主要结合着【深入理解Java虚拟机】一书当中整理了本篇博客

[转帖]ARM64 CentOS系统下MySQL使用jemalloc时的问题和解决方法

https://aijishu.com/a/1060000000321521 本文主要介绍在ARM64 CentOS系统下,MySQL使用jemalloc作为内存管理器时,内存占用问题的分析过程和解决方法。 Jemalloc 简介 Jemalloc是由Jason Evans在FreeBSD项目中引入

Spring Boot通过企业邮箱发邮件被Gmail退回的问题解决方法

这两天给我们开发的Chrome插件:[Youtube中文配音](https://youtube-dubbing.com/)增加了账户注册和登录功能,其中有一步是邮箱验证,所以这边会在Spring Boot后台给用户的邮箱发个验证信息。如果发邮件,之前的文章教程里就有,这里就不说了,着重说说这两天发现