Leetcode刷题详解——解码方法

news/2025/3/16 2:12:23/

1. 题目链接:91. 解码方法

2. 题目描述:

一条包含字母 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 = "06"
输出:0
解释:"06" 无法映射到 "F" ,因为存在前导零("6" 和 "06" 并不等价)。

提示:

  • 1 <= s.length <= 100
  • s 只包含数字,并且可能包含前导零。

3. 算法思路:

1. 状态表示:

i位置左结尾

2.状态转移方程

关于i位置的编码情况,我们可以分为下面两种情况:

  • i位置上的数单独解码成一个字母
  • i位置上的数与i-1位置上的数结合,解码成一个字母

下面我们就上面的两种解码情况,继续分析:

  1. i位置上的数单独解码成一个字母,就存在【解码成功】和【解码失败】两种情况 :

    1. 解码成功:当i位置上的数在[1,9]之间的时候,说明i位置上的数是可以单独解码的,那么此时[0,i]区间上的解码方法应该等于[0,i-1]区间上的解码方法。因为[0,i-1]区间上的所有解码结果,后面填写一个i位置解码后的字母就可以了。此时dp[i]=dp[i-1]

    2. 解码失败:当i位置上的数是0的时候,说明i位置上的数是不能单独解码的,那么此时[0,i]区间上不存在解码方法。因为i位置如果单独参与解码,但是解码失败了,那么前面做的努力就白费了。此时dp[i]=0;

  2. i位置上的数与i-1位置上的数结合在一起,解码成一个字母,也存在【解码成功】和【解码失败】两种情况:

    1. 解码成功:当结合的数在[10,26]之间的时候,说明[i-1,i]两个位置是可以解码成功的,那么此时[0,i]区间上的解码方法应该等于[0,i-2]区间上的解码方法,原因同上。此时dp[i]=d[i-2]

    2. 解码失败:当结合的数在[0,9][27,99]之间的时候,说明两个位置结合后解码失败(这里一定要注意00 01 02 03 04……这几种情况),那么此时[0,i]区间上的解码方法就不存在了,原因依旧同上,此时dp[i]=0

综上所述:dp[i]最终结果应该是上面四种情况下,解码成功的两种是累加和(因为我们关心的是解码方法,既然解码失败,就不用加入到最后结果中去),因此可以得到状态转移方程(dp[i]默认初始化为0):

  1. s[i]上的数在[1,9]区间时:dp[i]+=dp[i-1]

  2. s[i-1]s[i]上的数结合后,在[10,26]之间的时候:dp[i]+=dp[i-2];

如果上述两个判断不成立,说明没有解码方法,d[i]就是默认值0

3. 初始化:

方法1(直接初始化)
由于可能要用到i-1以及i-2位置上的dp值,因此要先初始化前两个位置

初始化dp[0]:

  1. s[0]==‘0’时,没有编码成功,结果dp[0]=0

  2. s[0]!=‘0’时,能编码成功,dp[0]=1

初始化dp[1]:

  1. s[1][1,9]之间时,能单独编码,此时dp[1]+=dp[0](原因同上,dp[1]默认为0
  2. s[0]s[1]结合后的数在[10,26]之间时,说明在前两个字符中,又有一种编码方式,此时dp[1]+=1

方法2(添加辅助位置初始化)

可以在最前面加上一个辅助结点,帮助我们初始化,使用这种技巧要注意两个点:

辅助结点里面的值要保证后续填表正确

下标的映射关系

4. 填表顺序

从左往右

5. 返回值

应该返回dp[n-1]的值,表示在[0,n-1]区间上的编码方法
请添加图片描述

4. C++算法代码

class Solution {
public:int numDecodings(string s) {int n=s.size();//创建一个dp表vector<int> dp(n);//初始化前两个位置dp[0]=s[0]!='0';//说明dp[0]在1~9之间if(n==1) return dp[0];//处理边界情况if(s[1]<='9'&&s[1]>='1') dp[1]+=dp[0];int t=(s[0]-'0')*10+s[1]-'0';if(t>=10&&t<=26) dp[1]+=1;//填表for(int i=2;i<n;i++){//如果单独编码if(s[i]<='9'&&s[i]>='1') dp[i]+=dp[i-1];//如果和前面的一个数联合起来编码int t=(s[i-1]-'0')*10+s[i]-'0';if(t>=10&&t<=26) dp[i]+=dp[i-2];}//返回结果return dp[n-1];}
};

http://www.ppmy.cn/news/1182130.html

相关文章

5.OsgEarth加载地形

愿你出走半生,归来仍是少年&#xff01; 在三维场景中除了使用影像体现出地貌情况&#xff0c;还需要通过地形体现出地势起伏&#xff0c;还原一个相对真实的三维虚拟世界。 osgEarth可通过直接加载Dem数据进行场景内的地形构建。 1.数据准备 由于我也没有高程数据&#xff0c…

Power BI 傻瓜入门 15. DAX功能带来乐趣

本章的内容包括&#xff1a; 了解DAX中的功能使用DAX函数制作定义明确的公式发现哪些DAX函数可以帮助解决复杂的数据计算或操作需求 在第14章中&#xff0c;我将讨论函数如何成为计算表达式中命名公式的一部分。作为提出计算表达式的人&#xff0c;您是为函数提供特定参数的人…

10款轻量型的嵌入式GUI库分享

LVGL LittlevGL是一个免费的开源图形库&#xff0c;提供了创建嵌入式GUI所需的一切&#xff0c;具有易于使用的图形元素、漂亮的视觉效果和低内存占用。 特点&#xff1a; 强大的构建模组 按钮、图表、列表、滑块、图像等 ​先进的图形 动画、反锯齿、半透明、平滑滚动 多样…

基于Pytest+Requests+Allure实现接口自动化测试!

一、整体结构 框架组成&#xff1a;pytestrequestsallure设计模式&#xff1a; 关键字驱动项目结构&#xff1a; 工具层&#xff1a;api_keyword/参数层&#xff1a;params/用例层&#xff1a;case/数据驱动&#xff1a;data_driver/数据层&#xff1a;data/逻辑层&#xff1a…

【C++项目】高并发内存池第六讲 当申请内存大于256K时的处理

目录 1.申请过程2.释放过程 1.申请过程 当申请的内存大于256kb时直接向堆中申请&#xff1a; static void* ConcurrentAlloc(size_t size) {if (size > MAX_BYTES){size_t alignSize SizeClass::RoundUp(size);size_t kpage alignSize >> PAGE_SHIFT;PageCache::…

BIOS MBR UEFI GPT详解

先来看下名词 启动方式&#xff1a; BIOS&#xff1a;Basic Input Output System&#xff0c;中文名称"基本输入输出系统"。 UEFI&#xff1a;Unified Extensible Firmware Interface&#xff0c;中文名称"统一的可扩展固件接口"。 Legacy&#xff1a;…

大厂面试题-JVM中的三色标记法是什么?

目录 问题分析 问题答案 问题分析 三色标记法是Java虚拟机(JVM)中垃圾回收算法的一种&#xff0c;主要用来标记内存中存活和需要回收的对象。 它的好处是&#xff0c;可以让JVM不发生或仅短时间发生STW(Stop The World)&#xff0c;从而达到清除JVM内存垃圾的目的&#xff…

Kotlin基础——枚举、When、in、for

枚举 声明只有值的枚举 enum class Color {RED, GREEN, BLUE }此外还可以增加属性和方法&#xff0c;如果需要在枚举类中定义方法&#xff0c;要使用分号把枚举常量列表和方法定义分开&#xff0c;这也是Kotlin唯一必须使用分号的地方 enum class Color(val r: Int, val g: …