leetcode每天一题:【罗马数字转整数】(简单)

1,143 阅读3分钟

这是我参与2022首次更文挑战的第16天,活动详情查看:2022首次更文挑战

题目描述

罗马数字转整数

罗马数字有I, V, X, LCD 和 M七种数字。

分别代表着1, 5, 10, 50100500 和 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的左边,分别代表着49
  • X可以放在L的左边和C的左边,分别代表着4090
  • C可以放在D的左边和M的左边,分别代表着400900

其它特殊情况不作考虑。比如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
};

image.png

第二种方法

和第一种方法一样,也是有个映射对象,但是它没有特殊情况的值。

因为特殊情况都是左边数字比右边数字小,所以我们可以判断如果左边数字比右边数字小,那么我们就认为是特殊情况,然后我们可以减去对应的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
};

image.png