首页 > 其他分享 >解码方法数问题

解码方法数问题

时间:2022-10-22 20:01:02浏览次数:65  
标签:int 解码 问题 process length str 方法 dp

解码方法数问题

作者: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];
    }
}

更多

算法和数据结构笔记

标签:int,解码,问题,process,length,str,方法,dp
From: https://www.cnblogs.com/greyzeng/p/16817155.html

相关文章

  • 爬虫中遇到登陆问题的解决方法
    在爬取网页时,由于会遇到登录问题而被阻止,此时通过改变头部信息来解决此问题以爬取京东商品页面为例1、先登录京东账号2、摁F12进入调试页面,然后刷新页面,在Network栏......
  • dremio 21 版本之后反射No File System scheme matches 问题解决
    实际属于一个老问题了,整理下,方便使用,主要是我们在使用反射的时候碰到的问题问题如下UnknownFormatConversionException:Conversion='Unknownformat(pdfs)conversio......
  • 区间问题----差分+离散化+前缀和
     《二维离散化+二维前缀和+二维双指针算法+二分+以点代二维区间》思路:首先,利用二分,将求解问题变成判断问题,二分边长关于在二维平面上的任意区域的数值问题可......
  • 单例 Bean 的线程安全问题
    最近面试遇到一个问题:单例Bean的线程安全问题怎么解决的。之前了解但是没有深究它的解决方法。大部分时候我们并没有在项目中使用多线程,所以很少有人会关注这个问题。......
  • dremio 23 s3 插件默认ssl 配置问题
    问题描述如下图  操作一般我们会按照(注意需要开启s3兼容模式),以上问题说明是依赖ssl,但是我们已经声明了不使用ssl  或者endpoint带上http如下,数据桶可......
  • 学习记录21接口新增方法、接口应用、适配器设计模式
    JDK8开始接口中新增的方法JDK7以前:接口中只能定义抽象方法JDK8的新特性:接口中可以定义有方法体的方法(类型:默认(抽象)、静态)JDK9的新特性:接口中可以定义私有方法在一......
  • Spring加载多个properties文件的方法
    1.用逗号隔开,写上多个properties文件的名字<context:property-placeholderlocation="jdbc.properties,jdbc2.properties"system-properties-mode="NEVER"/>2.......
  • 使用同步代码块解决线程安全问题
    使用同步代码块解决线程安全问题packageA_ShangGuiGu.Thread.ThreadDemo;​/***例子:三个窗口买票,使用实现Runnable接口的方法。*1.出现的问题:卖票过程中出现了重票,错......
  • #yyds干货盘点# 动态规划专题:跳台阶扩展问题
    1.简述:描述一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶(n为正整数)总共有多少种跳法。数据范围:进阶:空间复杂度  ,时间复杂......
  • element-ui form表单的input框按回车键后提交表单的问题
    在项目中,经常有表单提交操作,当提交的表单只有一行且均有必填校验时,按回车键会执行form的submit,但这个submit并不一定是我们想要的,因此要想办法避免此问题避免方法:通过在f......