每天一道LeetCode-----将数字集转成字母集,计算有多少种转换方式
Decode Ways
原题链接Decode Ways
每一个数字和一个字母对应,总共有26个字母,对于每一个或每两个数字,都有可能将其转化成字母,计算有多少中转换形式
以1221为例,所有的转换形式为1->’A’,2->’B’,12->’L’,21->’U’,22->’V’,所有可能的转换结果是
- ABBA ((1)(2)(2)(1))
- ABU ((1)(2)(21))
- AVA ((1)(22)(1))
- LBA ((12)(2)(1))
- LU ((12)(21))
假设给出的数字序列是s[0, 1, …, n],令dp[i - 1]表示s[0, 1, …, i-1]这个数字序列能够表示的所有转化结果个数,那么如何计算dp[i]呢
对于s[0, 1, …, i]这个数字序列的转化结果,可以分成两部分计算
- 由s[0, 1, …, i-1] + s[i]组成,即所有转化形式是s[0, 1, …, i-1]的转换结果后加s[i]表示的字母。如1221可以表示成由122的转换结果后加(1)表示的字母,即集合[ABB, AV, LB] + [A] = [ABBA, AVA, LBA],dp的表示形式为dp[i] += dp[i - 1]
- 由s[0, 1, …, i-2] + s[i-1, i]组成,即所有转化形式是s[0, 1, …, i-2]的转化结果后加由s[i-1, i]表示的字母。如1221可以表示成由12的转换结果后加(21)表示的字母,即集合[AB,L] + [U] = [ABU, LU],dp的表示形式为dp[i] += dp[i - 2]
所以直接动态规划计算即可,dp[i]与dp[i - 1]和dp[i - 2]有关,不过有几个边界条件,尤其注意’0’无法转换成对应字母的情况
- s[i] == ‘0’,s[i]不能表示字母,此时dp[i]与dp[i - 1]无关
- s[i - 1] == ‘0’,s[i-1, i]不能表示字母,此时dp[i]与dp[i - 2]无关
- i == 0 && s[0] != ‘0’,此时dp[0] = 1
- i == 1 && s[0] != ‘0’ && toNumber(s[0, 1]) <= 26,此时dp[1] = 2
代码如下
class Solution {
public:int numDecodings(string s) {if(s.empty()) return 0;vector<int> dp(s.size(), 0);for(int i = 0; i < s.size(); ++i){/* 由s[0,1,...,i-1]+s[i]组成 */if(s[i] != '0')dp[i] += (i == 0) ? 1 : dp[i - 1];/* 由s[0,1,...,i-2]+s[i-1,i]组成 */if(i > 0 && s[i - 1] != '0' && ((s[i - 1] - '0') * 10 + (s[i] - '0') <= 26))dp[i] += (i == 1) ? 1 : dp[i - 2];}return dp[s.size() - 1];}
};
代码中处理了i == 0和i == 1的情况,因为i == 0时dp[i - 1]无意义,i == 1时dp[i - 2]无意义
为什么程序中是dp[i] += dp[i - 1]而不是dp[i] += 1 + dp[i - 1]
因为dp[i - 1]表示由s[0, 1, …, i-1]表示的字母集,后面追加一个字母后个数没有改变
以1221为例,假设i == 3,则s[0, 1, …, i - 1]表示的字母集是[ABB, AV, LB],个数dp[i - 1]是3
当后面追加s[i]表示的字母A时,字母集变为[ABBA, AVA, LBA],个数没变,所有dp[i] = dp[i - 1]
当然,dp[i]在初始化时都至为0,所以只需要+=操作即可
Decode Ways II
原题链接Decode Ways II
要求和上面一样,不同的只是数字集s中可能包含’*’,这个符号可以表示1到9任意一个数字
思想还是动态规划,但是要处理的情况变多了,比如
- “*”可以可以表示”1”,”2”,…,”9”
- “*2”可以表示”12”,”22”
- “1*”可以表示”11”,”12”,…,”19”
- “3*”不能表示任何一个二位数的数字,因为超过了”26”
对于s[0, 1, …, i]由s[0, 1, …, i-1]+s[i]组成的情况,只是简单的多出s[i] == ‘*’的情况而已
而对于s[0, 1, …, j]由s[0, 1, …, i-2]+s[i-1, i]组成的情况,s[i-1, i]需要考虑多种情况,包括
- s[i - 1] == ‘*’ && s[i] != ‘*’
- s[i - 1] != ‘*’ && s[i] == ‘*’
- s[i - 1] == ‘*’ && s[i] == ‘*’
- s[i - 1] != ‘*’ && s[i] != ‘*’
当然,无论多出多少种情况也都不能忽略i == 0和i == 1的情况
首先考虑s[0, 1, …, i]由s[0, 1, …, i-1]+s[i]组成的情况
- 当s[i] == ‘‘时,s[i]可以表示9种数字,那么s[0, 1, …, i-1]后加s[i]时的组合个数就是dp[i - 1] 9。比如s[0, 1, …, i-1]表示的集合只有[A]一个,而s[i]可以表示’A’,’B’,…’J’九种,所以s[0, 1, …, i]表示的集合就变为[AA, AB, AC, AD, …, AJ]九种,自然是dp[i - 1] * 9
- 当s[i] != ‘*’时,s[i]只可以表示1种数字,那么dp[i] += dp[i - 1]即可
再考虑s[0, 1, …, i]由s[0, 1, …, i-2]+s[i-1, i]组成的情况
- 当s[i - 1] == ‘*’ && s[i] != ‘*’时
- 如果s[i] <= ‘6’,那么有两种即”1n”和”2n”(n表示s[i])
- 如果s[i] > ‘6’,那么只有一种”1n”(n表示s[i]),因为”2n”会超过”26”
- 当s[i - 1] != ‘*’ && s[i] == ‘*’时
- 如果s[i - 1] == ‘1’,那么有9种即”11”,”12”,…,”19”
- 如果s[i - 1] == ‘2’,那么有6中即”21”,”22”,…,”26”
- 如果s[i - 1] < ‘1’ || s[i - 1] > ‘2’,没有字母可以表示
- 当s[i - 1] == ‘*’ && s[i] == ‘*’时
- 有15种可能即”11”,”12”,….,”19”,”21”,”22”,…,”26”
- 当s[i - 1] != ‘*’ && s[i] != ‘*’时
- 如果s[i-1, i]表示的数字小于等于26,有1中可能
- 如果s[i-1, i]表示的数字大于26,没有字母可以表示
代码如下
class Solution {
public:int numDecodings(string s) {if(s.empty()) return 0;long long int base = 1;for(int i = 0; i < 9; ++i)base *= 10;base += 7;vector<long long int> dp(s.size(), 0);for(int i = 0; i < s.size(); ++i){if(s[i] != '0'){dp[i] += (s[i] == '*') ? ((i == 0) ? 2 : dp[i - 1] * 2) : ((i == 0) ? 1 : dp[i - 1]);}if(i > 0 && s[i - 1] != '0' && (s[i - 1] == '*' || s[i] == '*' || ((s[i - 1] - '0') * 10 + (s[i] - '0') <= 26))){if(s[i - 1] == '*' && s[i] != '*')dp[i] += (s[i] <= '6') ? ((i == 1) ? 9 : dp[i - 2] * 9) : ((i == 1) ? 1 : dp[i - 2] * 1);else if(s[i - 1] != '*' && s[i] == '*' && s[i - 1] <= '2')dp[i] += (s[i - 1] == '1') ? ((i == 1) ? 9 : dp[i - 2] * 9) : ((i == 1) ? 6 : dp[i - 2] * 6);else if(s[i - 1] == '*' && s[i] == '*')dp[i] += (i == 1) ? 15 : dp[i - 2] * 15;else if(s[i - 1] != '*' && s[i] != '*')dp[i] += (i == 1) ? 1 : dp[i - 2] * 1;}dp[i] %= base;}return dp[s.size() - 1];}
};
好多都是用了嵌套()?:表达式,如果不容易理解可以拆开
感觉这两道题不是在考动态规划而是在考脑筋急转弯啊,各种情况想的脑袋疼
每天一道LeetCode-----将数字集转成字母集,计算有多少种转换方式相关推荐
- jpg怎么转换成png格式?四种转换方式试试看
很多时候,我们需要将JPG(Joint Photographic Experts Group)格式转换成PNG(Portable Network Graphics)格式,从而便于图片的使用.那么,将J ...
- 怎么将PDF转换成CAD?有几种转换方式?转换时需要怎么做?
现在越来越多的人使用CAD制图,但是对于哪些刚开始选项CAD的人来说,并不简单,除了记住哪些快捷键之外,还需要懂得更多的操作技巧,就比如说,我们今天来说的,将PDF转换成CAD有几种方式,有时候我们收 ...
- 在一个笼子里同事养着一些鸡和兔子,你想了解有多少只鸡和兔,主任对你说:我只告诉你鸡和兔的总头数是16和总脚数是40,你能不能自己计算有多少只鸡和多少只兔?
帮一个小妹妹解决了一个C语言的编程题,题目如下 在一个笼子里同事养着一些鸡和兔子,你想了解有多少只鸡和兔,主任对你说:我只告诉你鸡和兔的总头数是16和总脚数是40,你能不能自己计算有多少只鸡和多少只兔 ...
- IDEA MAVEN项目打包成jar包的两种简单方式
IDEA MAVEN项目打包成jar包的两种简单方式 准备了两个打包方法 1.IEDA自带打包方法 2.用Maven插件maven-shade-plugin打包 IDEA自带打包 适用于任何打包,稍微 ...
- 怎么把Word转换成PDF?这几种转换神器分享给你
如何将Word文档转换成PDF格式文件呢?大家在日常中经常会使用这两种文件,有时候需要把PDF文件转换成Word文档来进行编辑,有时候又需要把Word文档转换成PDF来进行传输文件发送文件.PDF如何 ...
- mkv文件怎么转换成mp4?来看看这四种转换方式吧!
mkv文件怎么转换成mp4?在很多小伙伴看到,图片就是图片,音频就是音频,视频就是视频,它们展现给人们的效果都差不多.但实际上,不管是图片.视频还是音频文件,其中一个重要的区别在于它们的文件格式可能是 ...
- cad怎么转换成jpg图片?试试看这几种转换方式
cad怎么转换成jpg图片?CAD (Computer-Aided Design) 是一种广泛应用于工程.建筑和设计领域的软件,它可以帮助用户进行三维建模和设计.而 JPG (Joint Photog ...
- 卡特兰数:2N个人排队买电影票,N个人持5元买票,N个人持10元买票.售票处在售票前只有票没有钱,票价5元 ,问有多少种排队方式 能让2N个人顺利买票,并且输出所有排队队列(不会因为找钱问题)
分析 n = 0 时,队列为空,可以认为只有一种: n = 1 时,队列:5 ,10 共有1种: n = 2 时 ,队列: 5, 10,5,10 5,5,10,10 共有两种 n = 3时, 队 ...
- mpg文件怎么转成mp4?四招即刻转换!
mpg文件怎么转成mp4?虽然MPG是一种通用的视频格式,但是在某些设备或软件上仍然无法正常播放.而MP4格式则是一种应用更广泛的视频格式,几乎所有的设备和软件都能够支持播放,因此将MPG转换为MP4 ...
最新文章
- Python爬虫之urllib和requests哪个好用--urllib和requests的区别
- Python学习-28.Python中的列表切片
- java开发学不会_JAVA学不会,快期末了,怎么办?
- java项目分页_Java项目实战分页类
- mongodb for java_【MongoDB for Java】Java操作MongoDB
- 最全面的linux网站
- php购物车点击删除,求助 购物车 用session删除 列表的一条
- 1、登录模块测试用例
- 在线文本加密解密工具
- python绘制小狗_SAI教程:绘画小狗手绘板教程
- FMCW雷达多运动目标检测
- 超详细纯前端导出excel并完成各种样式的修改(xlsx-style)
- STM32 DFU下载与 DFU生成工具
- A1、A2、A3、A4纸都是多大尺寸
- 关于云音乐数据治理的实践与思考
- 探讨Linux CPU的上下文切换原由
- 大学生期末考试html,《大学英语(第二学期)》期末考试试卷(A卷)
- matlab subs什么意思,什么是matlab subs函数?
- 顶会CIKM‘21论文解读:基于图神经网络的人类行为轨迹恢复模型
- EPS创建三维模型-(osgb数据在EPS中的转换数据)
热门文章
- idea git 过滤target_IDEA + maven 零基础构建 java agent 项目
- Java黑皮书课后题第10章:10.24(实现Character类)在Java库中提供了Character类,给出你自己对这个类的实现(将新类命名为MyCharacter)
- Java黑皮书课后题第9章:*9.6(秒表)设计一个名为StopWatch的类,该类包含……。编写一个测试程序,用于测量使用选择排序对100000个数字进行排序的执行时间
- Java黑皮书课后题第7章:7.26(完全相同的数组)如果两个数组list1和list2的对应元素都相等,认为完全相同。编写一个测试程序,提示用户输入两个整数列表,然后显示这两个列表是否完全相同
- Java黑皮书课后题第3章:**3.22(几何:点是否在圆内)编写程序,提示用户输入一个点(x,y),然后检查这个点是否在以(0,0)为圆心、半径为10的圆内
- Java黑皮书课后题第3章:**3.4(随机月份)编写一个随机产生1和12之间整数的程序,并根据数组1,2,3...显示对应的月份
- 浙江大华2011.10.10校园招聘会笔试题
- Ubuntu系统---NVIDIA 驱动安装
- ubuntu16.04 关闭防火墙的方法
- SQL Server学习之路(五):“增删改查”之“改”