这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战
题目描述
罗马数字有I, V, X, L,C,D 和 M七种数字。
分别代表着1, 5, 10, 50,100,500 和 1000七种现代数字。
比如罗马数字II代表着数字(1 + 1),罗马数字VI代表着数字6(5 + 1),罗马数字XXVIII代表着数字28(10 + 10 + 5 + 1 + 1 + 1),罗马数字LXI代表着数字61(50 + 10 + 1)。
一般大的数字在左边,小的数字在右边,然后把它对应的数字一起相加,就是最后代表的数字。
但是有例外的情况,如下:
比如4并不是写成IIII,而是IV。等同于(5 - 1)。
总共有六种特殊情况,如下:
I可以放在V的左边和X的左边,分别代表着4和9。X可以放在L的左边和C的左边,分别代表着40和90。C可以放在D的左边和M的左边,分别代表着400和900。
其它特殊情况不作考虑。比如IC,并不是99,而是101(100 + 1)。
思路分析
第一种方法
可以使用策略模式,使用一个对象做映射,罗马数字做key,具体的数字做value。
这里我还把特殊的情况(比如IV,IX,XL等)也写到对象里面。
然后遍历输入的罗马数字
如果当前字符和下一个字符相加后在对象里面可以匹配到,则需要加上对应的value值。然后索引需要跳过下一个。
如果没有匹配到,则只需加上当前遍历的罗马数字对应的value值。
最后返回加好的数字即可。
/**
* @param {string} s
* @return {number}
*/
var romanToInt = function (s) {
var mappingRoman = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000,
IV: 4,
IX: 9,
XL: 40,
XC: 90,
CD: 400,
CM: 900
}
var num = 0
for (let i = 0; i < s.length; i++) {
const ss = s[i] + s[i + 1]
if (mappingRoman[ss]) {
num += mappingRoman[ss]
i = i + 1
} else {
num += mappingRoman[s[i]]
}
}
return num
};
第二种方法
和第一种方法一样,也是有个映射对象,但是它没有特殊情况的值。
因为特殊情况都是左边数字比右边数字小,所以我们可以判断如果左边数字比右边数字小,那么我们就认为是特殊情况,然后我们可以减去对应的value值。其它情况都可以加上对应的value值。
代码如下:
/**
* @param {string} s
* @return {number}
*/
var romanToInt = function (s) {
var mappingRoman = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000
}
var num = 0
for (let i = 0; i < s.length; i++) {
if (i + 1 <= s.length - 1 && mappingRoman[s[i]] < mappingRoman[s[i + 1]]) {
num -= mappingRoman[s[i]]
} else {
num += mappingRoman[s[i]]
}
}
return num
};