题目描述

  题目跟前面13题描述一样,就是问题变为整数转成罗马数字。

思路

  上一道题罗马数字转整数比较简单,因为不存在罗马数字表示冲突的问题,即不存在一个罗马数字对应多个整数。而这个问题中,就要考虑一下这个问题了,因为如果不加以约束的话,一个整数可以用多种罗马数字来表示。比如对于2000:

2000 = 1000 + 1000 = M + M,即MM
2000 = 1000 + 900 + 100 = M + CM + C,即MCMC

  于是,我特地查了一下,罗马数字的排列规则是从左到右尽可能用最大的数字来表示。那么,就像之前那样,准备好一个字典,反过来以整数为键,罗马数字为值,存放13种键-值组合。
  然后,只要整数num(待转换的数)不为0,就在每次循环里找到一个离他最近的罗马数字对应的整数n,记录该罗马数字,然后让num-n,继续循环,直到num=0为止。
伪代码描述:

buf = {1000:‘M’, 900:‘CM’, 500:‘D’, 400:‘CD’, 100:‘C’, 90:‘XC’,
50:‘L’, 40:‘XL’, 10:‘X’, 9:‘IX’, 5:‘V’, 4:‘IV’, 1:‘I’}
res = “”
while num != 0
  找到最接近num的整数n
  res += buf[n]
  num -= n
return res

python代码(low版)

class Solution:def intToRoman(self, num: int) -> str:buf = {1:'I', 5:'V', 10:'X', 50:'L', 100:'C', 500:'D', 1000:'M', 4:'IV', 9:'IX',40:'XL', 90:'XC', 400:'CD', 900:'CM'}d_keys = list(buf.keys())d_keys.sort(reverse = True)if num in d_keys:return buf[num]res = ''t = 0while num != 0:for n in d_keys:t = num - nif t >= 0:res += buf[n]num -= nbreakreturn res

  这是第一版代码,运行时间80ms,慢得一*,观察代码,可以看见真的憨憨,创建字典时竟然乱序,后面还要排序,而且在while里每次for都是从第一个元素开始,这无疑浪费时间,从上次break的位置接着往后找他不香吗?而且再仔细想想,也没必要先判断num是否是正好对应现成的,反正in操作的原理也是循环,所以这里可以删掉。

改进一点的python代码

class Solution:def intToRoman(self, num: int) -> str:buf = {1000:'M', 900:'CM', 500:'D', 400:'CD', 100:'C', 90:'XC',50:'L', 40:'XL', 10:'X', 9:'IX', 5:'V', 4:'IV', 1:'I'}d_keys = list(buf.keys())res = ''idx = 0size = d_keys.__len__()while num != 0:for i in range(idx, size):t = num - d_keys[i]if t >= 0:res += buf[d_keys[i]]num -= d_keys[i]breakidx = ireturn res

提交,运行时间64ms,还是有点慢,无奈去看了看官方题解,原来我前面的思路是贪心算法的思路,这我还真没想到。

最终代码

  官方题解的代码给了我灵感,原来可以这样写:

class Solution:def intToRoman(self, num: int) -> str:buf = {1000:'M', 900:'CM', 500:'D', 400:'CD', 100:'C', 90:'XC',50:'L', 40:'XL', 10:'X', 9:'IX', 5:'V', 4:'IV', 1:'I'}res = ""for n in buf.keys():if num == 0:breakquotient, num = divmod(num, n)res += buf[n] * quotientreturn res

  这样写的好处就在于一遍循环就能解决问题,那58来说,前面的代码在执行到num = 3时,会做3次for循环,而这3次循环都都几乎是同样的操作,效率极低,而这里用到的字符串“乘法”操作,在这种情况下就极大的提高效率,真香!

C++实现

class Solution {public:string intToRoman(int num) {string res;/*map <int, string, greater<int>> dict = {{1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"},{100, "C"}, {90, "XC"}, {50, "L"}, {40, "XL"}, {10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"}, {1, "I"}};for(auto &t : dict){if(num == 0){break;}while(num >= t.first){num -= t.first;res += dict[t.first];}}*///更快的解法int key[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};string values[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};for(int i = 0; i < 13; i++){if(num == 0){break;}while(num >= key[i]){num -= key[i];res += values[i];}}return res;}
};

  注释掉的地方是用的map,运行时间32ms,只比python快了20ms,也许是创建map比较耗时的原因吧,我觉得还能更快,所以把键值对拆开成两个数组,这样下来运行时间是12ms。
  还有就是,就算给map的初值是按顺序写的,但map内部实现还是无序,因此还要在map的类型说明里加上greater参数,指明按int(这里就是键)降序排序。我第一次没加这个参数,结果答案全是“IIIIIIII…”,看了其他大佬的博客才明白,学到了学到了。

LeetCode题目笔记--12.整数转罗马数字相关推荐

  1. leetcode力扣12. 整数转罗马数字

    罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符          数值 I             1 V             5 X             10 L ...

  2. LeetCode 11盛水最多的容器12整数转罗马数字

    目录 盛水最多的容器 题目描述 分析 整数转罗马数字 题目描述: 分析 结语 盛水最多的容器 公众号:bigsai,回复进群加入打卡,回复bigsai获取3GB的pdf资源.点赞再看,养成习惯! 题目 ...

  3. Leetcode算法Java全解答--12. 整数转罗马数字

    Leetcode算法Java全解答–12. 整数转罗马数字 文章目录 Leetcode算法Java全解答--12. 整数转罗马数字 题目 想法 结果 总结 代码 我的答案 大佬们的答案 测试用例 其他 ...

  4. LeetCode (12.整数转罗马数字)JAVA StringBuffer

    LeetCode (12.整数转罗马数字)JAVA StringBuffer 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 1 ...

  5. 12. 整数转罗马数字 (Java解题 贪心思想)

    LeetCode - 12. 整数转罗马数字 题目描述 解题分析 code 总结 题目描述 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L ...

  6. 12.整数转罗马数字-LeetCode

    1. 问题描述 这里直接采用的是leetcode上面的问题描述 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 例如, 罗马数字 2 写做 II ,即为两个并列的 1.12 写做  ...

  7. Leetcode No.12 整数转罗马数字

    题目描述 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符          数值 I             1 V             5 X             ...

  8. LeetCode【11--盛水最多的容器】LeetCode【12 -- 整数转罗马数字】

    盛水最多的容器 题目描述 给定 n 个非负整数 a1,a2,-,an,每个数代表坐标中的一个点 (i, ai) .在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0 ...

  9. LeetCode(cai鸟之路)12 整数转罗马数字

    题目描述 罗马数字包含以下七种字符: I, V, X, L,C,D 和 M. 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如, 罗马数字 2 写做 II , ...

最新文章

  1. Android 自定义View之3D骰子旋转
  2. nagios自定义监控API插件
  3. CodeChef--SEPT14小结
  4. bzoj2938(ac自动机)
  5. editplus 配置 golang 开发调试环境
  6. hdu 1850 基础尼姆博奕
  7. 嵌入式系统HAL原理与BSP的实现方法
  8. linux fedora下实现锐捷认证
  9. SpringBoot怎么直接访问templates下的html页面
  10. java 创建ssh用户秘钥,安装Java、Maven、Git,以及生成、拷贝密钥
  11. 具体数学-第7课(取整基础)
  12. Layui组件和文档下载
  13. Windows10原神二次元美化主题工具包分享
  14. 机器学习常见算法分类
  15. 【Python】ID3算法的实现
  16. matlab插值表,[转载]matlab插值介绍
  17. java 面向对象三个特征_[Java] 面向对象的三个特征与含义
  18. R语言中 attach()与detach(),及with()的使用
  19. 沃尔玛中国将采用唯链雷神区块链追踪食品供应链
  20. Jenkins系列之——第三章 Jenkins编译的第一个项目

热门文章

  1. 某面试官分享经验:看求职者第一眼,开口说第一句话,面试结果就差不多定了,准确率高达90%以上...
  2. 【智力题】大厂最爱问的智力题
  3. 视觉设计是怎样影响用户体验的
  4. 以太坊智能合约中 pragma solidity^0.6.10 是什么意思
  5. 移动通信网络规划:毫米波技术
  6. 银行使用计算机实现个人存款,江苏省计算机二级考试基础知识题
  7. matlab软件的功能介绍
  8. 过拟和处理方法.md
  9. 如何搭建自己的网站_如何让别人看到自己编写的网页_IIS创建网站
  10. 传统文化中,“七”代表着什么?