标签:
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”,與進位制無關。一般認為羅馬數字只用來記數,而不作演算。
这其中有一个很有意思的问题:
对于这道题,真正有用的规则只有前面所述黑体的部分,那我们是“从前往后”扫描计算还是“从后往前”扫描呢?
* 如果是从前往后,那么假定已经扫描过的位置都是已经处理了的(即这一位的值已经被计算过):
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 在处理过程中的波动理论上也更小,而且符合我们的假定:即只处理还未扫描到的位,已经扫描到的不再做任何 “补救” 形态的处理。
下面,把两种策略的代码都贴出来:
“从前往后”的策略:
1 class Solution: 2 # @param {string} s 3 # @return {integer} 4 def romanToInt(self, s): 5 roman = { 6 "I": 1, 7 "V": 5, 8 "X": 10, 9 "L": 50, 10 "C": 100, 11 "D": 500, 12 "M": 1000 13 } 14 ans = roman[s[0]] 15 for i in range(1, len(s)): 16 if roman[s[i]] > roman[s[i-1]]: 17 ans += roman[s[i]] - 2*roman[s[i-1]] 18 else: 19 ans += roman[s[i]] 20 return ans
“从后往前”的策略:
1 class Solution: 2 # @param {string} s 3 # @return {integer} 4 def romanToInt(self, s): 5 roman = { 6 "I": 1, 7 "V": 5, 8 "X": 10, 9 "L": 50, 10 "C": 100, 11 "D": 500, 12 "M": 1000 13 } 14 n = len(s) 15 ans = roman[s[n-1]] 16 i = n-2 17 while i >= 0: 18 if roman[s[i]] >= roman[s[i+1]]: 19 ans += roman[s[i]] 20 else: 21 ans -= roman[s[i]] 22 i -= 1 23 return ans
Reference:
http://blog.csdn.net/jellyyin/article/details/13165731
标签:
原文地址:http://www.cnblogs.com/maples7/p/4732762.html