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-----将数字集转成字母集,计算有多少种转换方式相关推荐

  1. jpg怎么转换成png格式?四种转换方式试试看

    很多时候,我们需要将JPG(Joint Photographic Experts Group)格式转换成PNG(Portable Network Graphics)格式,从而便于图片的使用.那么,将J ...

  2. 怎么将PDF转换成CAD?有几种转换方式?转换时需要怎么做?

    现在越来越多的人使用CAD制图,但是对于哪些刚开始选项CAD的人来说,并不简单,除了记住哪些快捷键之外,还需要懂得更多的操作技巧,就比如说,我们今天来说的,将PDF转换成CAD有几种方式,有时候我们收 ...

  3. 在一个笼子里同事养着一些鸡和兔子,你想了解有多少只鸡和兔,主任对你说:我只告诉你鸡和兔的总头数是16和总脚数是40,你能不能自己计算有多少只鸡和多少只兔?

    帮一个小妹妹解决了一个C语言的编程题,题目如下 在一个笼子里同事养着一些鸡和兔子,你想了解有多少只鸡和兔,主任对你说:我只告诉你鸡和兔的总头数是16和总脚数是40,你能不能自己计算有多少只鸡和多少只兔 ...

  4. IDEA MAVEN项目打包成jar包的两种简单方式

    IDEA MAVEN项目打包成jar包的两种简单方式 准备了两个打包方法 1.IEDA自带打包方法 2.用Maven插件maven-shade-plugin打包 IDEA自带打包 适用于任何打包,稍微 ...

  5. 怎么把Word转换成PDF?这几种转换神器分享给你

    如何将Word文档转换成PDF格式文件呢?大家在日常中经常会使用这两种文件,有时候需要把PDF文件转换成Word文档来进行编辑,有时候又需要把Word文档转换成PDF来进行传输文件发送文件.PDF如何 ...

  6. mkv文件怎么转换成mp4?来看看这四种转换方式吧!

    mkv文件怎么转换成mp4?在很多小伙伴看到,图片就是图片,音频就是音频,视频就是视频,它们展现给人们的效果都差不多.但实际上,不管是图片.视频还是音频文件,其中一个重要的区别在于它们的文件格式可能是 ...

  7. cad怎么转换成jpg图片?试试看这几种转换方式

    cad怎么转换成jpg图片?CAD (Computer-Aided Design) 是一种广泛应用于工程.建筑和设计领域的软件,它可以帮助用户进行三维建模和设计.而 JPG (Joint Photog ...

  8. 卡特兰数: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时, 队 ...

  9. mpg文件怎么转成mp4?四招即刻转换!

    mpg文件怎么转成mp4?虽然MPG是一种通用的视频格式,但是在某些设备或软件上仍然无法正常播放.而MP4格式则是一种应用更广泛的视频格式,几乎所有的设备和软件都能够支持播放,因此将MPG转换为MP4 ...

最新文章

  1. Python爬虫之urllib和requests哪个好用--urllib和requests的区别
  2. Python学习-28.Python中的列表切片
  3. java开发学不会_JAVA学不会,快期末了,怎么办?
  4. java项目分页_Java项目实战分页类
  5. mongodb for java_【MongoDB for Java】Java操作MongoDB
  6. 最全面的linux网站
  7. php购物车点击删除,求助 购物车 用session删除 列表的一条
  8. 1、登录模块测试用例
  9. 在线文本加密解密工具
  10. python绘制小狗_SAI教程:绘画小狗手绘板教程
  11. FMCW雷达多运动目标检测
  12. 超详细纯前端导出excel并完成各种样式的修改(xlsx-style)
  13. STM32 DFU下载与 DFU生成工具
  14. A1、A2、A3、A4纸都是多大尺寸
  15. 关于云音乐数据治理的实践与思考
  16. 探讨Linux CPU的上下文切换原由
  17. 大学生期末考试html,《大学英语(第二学期)》期末考试试卷(A卷)
  18. matlab subs什么意思,什么是matlab subs函数?
  19. 顶会CIKM‘21论文解读:基于图神经网络的人类行为轨迹恢复模型
  20. EPS创建三维模型-(osgb数据在EPS中的转换数据)

热门文章

  1. idea git 过滤target_IDEA + maven 零基础构建 java agent 项目
  2. Java黑皮书课后题第10章:10.24(实现Character类)在Java库中提供了Character类,给出你自己对这个类的实现(将新类命名为MyCharacter)
  3. Java黑皮书课后题第9章:*9.6(秒表)设计一个名为StopWatch的类,该类包含……。编写一个测试程序,用于测量使用选择排序对100000个数字进行排序的执行时间
  4. Java黑皮书课后题第7章:7.26(完全相同的数组)如果两个数组list1和list2的对应元素都相等,认为完全相同。编写一个测试程序,提示用户输入两个整数列表,然后显示这两个列表是否完全相同
  5. Java黑皮书课后题第3章:**3.22(几何:点是否在圆内)编写程序,提示用户输入一个点(x,y),然后检查这个点是否在以(0,0)为圆心、半径为10的圆内
  6. Java黑皮书课后题第3章:**3.4(随机月份)编写一个随机产生1和12之间整数的程序,并根据数组1,2,3...显示对应的月份
  7. 浙江大华2011.10.10校园招聘会笔试题
  8. Ubuntu系统---NVIDIA 驱动安装
  9. ubuntu16.04 关闭防火墙的方法
  10. SQL Server学习之路(五):“增删改查”之“改”