【LeetCode】Roman to Integer & Integer to Roman
Roman to Integer
Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.
首先学习一下罗马数字的规则:
羅馬數字共有7個,即I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000)。按照下述的規則可以表示任意正整數。需要注意的是罗马数字中没有“0”,與進位制無關。一般認為羅馬數字只用來記數,而不作演算。
- 重複數次:一個羅馬數字重複幾次,就表示這個數的幾倍。
- 右加左減:
- 在較大的羅馬數字的右邊記上較小的羅馬數字,表示大數字加小數字。
- 在較大的羅馬數字的左邊記上較小的羅馬數字,表示大數字减小數字。
- 左减的数字有限制,仅限于I、X、C。比如45不可以写成VL,只能是XLV
- 但是,左減時不可跨越一個位數。比如,99不可以用IC (100 - 1) 表示,而是用XCIX( (100 - 10) + (10 - 1) )表示。(等同於阿拉伯數字每位數字分別表示。)
- 左減數字必須為一位,比如8寫成VIII,而非IIX。
- 右加數字不可連續超過三位,比如14寫成XIV,而非XIIII。(見下方“數碼限制”一項。)
- 加線乘千:
- 在羅馬數字的上方加上一條橫線或者加上下標的Ⅿ,表示將這個數乘以1000,即是原數的1000倍。
- 同理,如果上方有兩條橫線,即是原數的1000000(1000^2)倍。
这其中有一个很有意思的问题:
对于这道题,真正有用的规则只有前面所述黑体的部分,那我们是“从前往后”扫描计算还是“从后往前”扫描呢?
* 如果是从前往后,那么假定已经扫描过的位置都是已经处理了的(即这一位的值已经被计算过):
1. 当 s[i] > s[i-1],应该是 s[i] - s[i-1],但是此时 s[i-1] 已经被处理并且一定是被加进了 ans (对 s[i-2] 分情况讨论便知),所以此时需要 ans += s[i] - 2*s[i-1];
2. 当 s[i] <= s[i-1],应该是 加上 s[i-1],这没什么问题。
* 如果是从后往前,那么假定已经扫描过的位置都是已经处理了的(即这一位的值已经被计算过):
1. 当 s[i] >= s[i+1],把 s[i] 加进去即可( s[i+1] 是加进 ans 还是 减进 ans 的都没有影响),样例有 XCIX(99);
2. 当 s[i] < s[i+1], 把 s[i] 减进 ans 即可。
所以,相比之下“从后往前”的策略是更规范和统一,逻辑上也更清晰,ans 在处理过程中的波动理论上也更小,而且符合我们的假定:即只处理还未扫描到的位,已经扫描到的不再做任何 “补救” 形态的处理。
下面,把两种策略的代码都贴出来:
“从前往后”的策略:
class Solution:
# @param {string} s
# @return {integer}
def romanToInt(self, s):
roman = {
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000
}
ans = roman[s[0]]
for i in range(1, len(s)):
if roman[s[i]] > roman[s[i-1]]:
ans += roman[s[i]] - 2*roman[s[i-1]]
else:
ans += roman[s[i]]
return ans
“从后往前”的策略:
class Solution:
# @param {string} s
# @return {integer}
def romanToInt(self, s):
roman = {
"I": 1,
"V": 5,
"X": 10,
"L": 50,
"C": 100,
"D": 500,
"M": 1000
}
n = len(s)
ans = roman[s[n-1]]
i = n-2
while i >= 0:
if roman[s[i]] >= roman[s[i+1]]:
ans += roman[s[i]]
else:
ans -= roman[s[i]]
i -= 1
return ans
Reference:
http://blog.csdn.net/jellyyin/article/details/13165731
Integer to Roman
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
Solution:
反过来的关键在于找出能表示所有的数的“基本元”的集合,然后从数值大到小排列,依次从num里面减去,同时构造出罗马数字串,直至num为0。
那么哪些是我们要找的“基本元”呢?
让我们从小数字来看,首先 1 是已经存在的基本元(I),2和3则可以用 I 的重复来表示,但是 4 却已经不能用更 4 个 I 来表示了(受 “右加數字不可連續超過三位” 规则限制),而只能用 5-1 也就是 IV 来表示了。
至此,6 - 8 也可以用 V 和 I 的组合表示了,但是对于 9,首先不能是 VIIII,5+4(VIV)也不行( I 位的符号受“右加左减”限制存在矛盾),而只能是 10 - 1 (IX)。
至此,个位数的情况已经穷尽,而更高数量级的数字与此同理可以找出“基本元”,较小数量级的数又可以由已经找出的“基本元”的合法组合来表示,这就好比我们熟知的人民币数值系统。
代码如下:
class Solution:
# @param {integer} num
# @return {string}
def intToRoman(self, num):
values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1]
numerals = ["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"]
ans, i = "", 0
while num:
ans += (num//values[i]) * numerals[i]
num %= values[i]
i += 1
return ans
【LeetCode】Roman to Integer & Integer to Roman的更多相关文章
- 【LeetCode】7、Reverse Integer(整数反转)
题目等级:Easy 题目描述: Given a 32-bit signed integer, reverse digits of an integer. Example 1: Input: 123 O ...
- 【LeetCode】8. String to Integer (atoi) 字符串转换整数
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:字符串转整数,atoi,题解,Leetcode, 力扣,P ...
- 【LeetCode】8. String to Integer (atoi) 字符串转整数
题目: Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input ca ...
- 【LeetCode】7 & 8 - Reverse Integer & String to Integer (atoi)
7 - Reverse digits of an integer. Example1: x = 123, return 321Example2: x = -123, return -321 Notic ...
- 【leetcode】8. String to Integer (atoi)
题目描述: Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input ...
- 【LeetCode】008. String to Integer (atoi)
Implement atoi to convert a string to an integer. Hint: Carefully consider all possible input cases. ...
- 【leetcode】1237. Find Positive Integer Solution for a Given Equation
题目如下: Given a function f(x, y) and a value z, return all positive integer pairs x and y where f(x,y ...
- 【LeetCode】9、Palindrome Number(回文数)
题目等级:Easy 题目描述: Determine whether an integer is a palindrome. An integer is a palindrome when it rea ...
- 【LeetCode】397. Integer Replacement 解题报告(Python)
[LeetCode]397. Integer Replacement 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/inte ...
- 【LeetCode】Minimum Depth of Binary Tree 二叉树的最小深度 java
[LeetCode]Minimum Depth of Binary Tree Given a binary tree, find its minimum depth. The minimum dept ...
随机推荐
- Ecshop 后台增加一个左侧列表菜单menu菜单的方法
Ecshop 后台增加一个左侧列表菜单menu菜单需要修改三个文件:/admin/includes/inc_menu.php/admin/includes/inc_priv.php/languages ...
- 部署私有的Nuget服务器
1.查看官方的部署文档:http://docs.nuget.org/Create/Hosting-Your-Own-NuGet-Feeds 2.使用开源的项目:https://github.com/h ...
- P53 T5
北京某高校可用的电话号码有以下几类:校内电话号码由4位数字,第1位数字不是0:校外电话又分为本市电话和外地电话两类,拔校外电话需先拔0,若是本市电话则再接着拔8位数字(第一位不是0),若是外地电话则拔 ...
- f(n) hdu 2582
calculate the f(n) . (3<=n<=1000000)f(n)= Gcd(3)+Gcd(4)+-+Gcd(i)+-+Gcd(n).Gcd(n)=gcd(C[n][1],C ...
- Android中Activity加入Fragment使用注意事项及常用技巧
Fragment中AlertDialog弹出窗口的使用 Fragment默认不具有Content的一些方法和属性,因此在Activity中可以使用的一些方法在Fragment中使用就需要一些小技巧了 ...
- JavaScript 继承
许多OO语言都支持两种继承方式,接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.由于在ECMAScript中,函数没有签名,无法实现接口继承,只支持实现继承,而且其实现继承主要 ...
- [转]SPICE仿真软件基础(整理)
现在常用的SPICE仿真软件为方便用户使用都提供了较好的用户界面,在用仿真库中的元器件连成原理图后就可以进行仿真(当然要设置必要的仿真参数),但实际上只是用原理图自动产生了SPICE的格式语句,还是要 ...
- PL/SQL Developer记住用户名密码
在使用PL/SQL Developer时,为了工作方便希望PL/SQL Developer记住登录Oracle的用户名和密码: 设置方法:PL/SQL Developer ->tools-> ...
- 百度前端技术学院2015JavaScript基础部分代码实现
2. JavaScript数据类型及语言基础(一) 2.1 任务描述 创建一个JavaScript文件,比如util.js: 实践判断各种数据类型的方法,并在util.js中实现以下方法: / ...
- dedecms购物车商品添加删除数量改变方式变成ajax
简单的做了一下修改,模板用的它默认的模板,感觉之前全是表单提交很不爽用的 修改的相关文件:/plus/posttocar.php, /plus/car.php,/templets/plus/car.h ...