首页 简历|笔试面试

13、罗马数字转整数

  • 25年9月4日 发布
  • 251.12KB 共5页
13、罗马数字转整数13、罗马数字转整数13、罗马数字转整数13、罗马数字转整数13、罗马数字转整数

13、罗马数字转整数

鲁迅说过,三天不刷 LeetCode,手里发痒,今天继续来刷《二哥的 LeetCode 刷

题笔记》吧。

题意

给你一个罗马数字,要求你给出它相应的整数。

至于罗马数字是什么,第 12 题已经解释过了,这里就不再赘述。

难度

简单

示例

示例 1:

输入: s = "III"

输出: 3

示例 2:

输入: s = "IV"

输出: 4

示例 3:

输入: s = "IX"

输出: 9

示例 4:

输入: s = "LVIII"

输出: 58

解释: L = 50, V= 5, III = 3.

示例 5:

输入: s = "MCMXCIV"

输出: 1994

解释: M = 1000, CM = 900, XC = 90, IV = 4.

分析 1

这道题目和第 12 题是相反的,第 12 题是整数转罗马数字,这道题目是罗马数字转整

数。

我们可以先把罗马数字和整数的对应关系列出来:

我们可以发现,罗马数字和整数的对应关系是一一对应的,所以我们可以把这些对应关系

放到一个 Map 中,然后遍历罗马数字,依次取出对应的整数,然后相加即可。

需要注意的是,如果一个较小的数字在较大的数字前面,比如 IV、IX、XL、XC、CD、

CM,需要减去这个较小的数字(因为它表示的是一个减法操作,如 IV 表示 4)。

来看题解:

class Solution {

public int romanToInt(String s) {

// 创建一个哈希表存储罗马数字和对应的整数值

Map<Character, Integer> romanMap = new HashMap<>();

romanMap.put('I', 1);

romanMap.put('V', 5);

romanMap.put('X', 10);

romanMap.put('L', 50);

romanMap.put('C', 100);

romanMap.put('D', 500);

romanMap.put('M', 1000);

int sum = 0;

int prevValue = 0;

// 从后向前遍历罗马数字字符串

for (int i = s.length() - 1; i >= 0; i--) {

int currValue = romanMap.get(s.charAt(i));

// 如果当前值小于之前的值,则减去当前值;否则,加上当前值

if (currValue < prevValue) {

sum -= currValue;

} else {

sum += currValue;

}

prevValue = currValue;

}

return sum;

}

}

我们首先创建一个哈希表来存储罗马数字字符及其对应的整数值。

然后,从字符串的最后一个字符开始向前遍历(这样可以更方便地处理减法情况)。

对于每个字符,我们查找其对应的整数值。

如果当前字符代表的数值小于其右侧的数值,这意味着我们遇到了一个减法情况(如 IV

或 IX),因此我们从总和中减去这个数值。

如果当前字符代表的数值大于等于其右侧的数值,我们就简单地加上这个数值。

最终累加的结果就是罗马数字字符串所表示的整数值。

来看一下题解效率,还不错:

013.%E7%BD%97%E9%A9%AC%E6%95%B0%E5%AD%97%E8%BD%AC%E6%95%B4%E

6%95%B0-20240122105021.png

分析 2

我们可以把上面的代码再优化一下,把 Map 换成数组,这样效率会更高一点。

class Solution {

public int romanToInt(String s) {

int[] values = new int[128]; // ASCII 码的范围足够覆盖所有字符

values['I'] = 1;

values['V'] = 5;

values['X'] = 10;

values['L'] = 50;

values['C'] = 100;

values['D'] = 500;

values['M'] = 1000;

int sum = 0;

int prevValue = 0;

for (int i = s.length() - 1; i >= 0; i--) {

int currValue = values[s.charAt(i)];

if (currValue < prevValue) {

sum -= currValue;

} else {

sum += currValue;

}

prevValue = currValue;

}

return sum;

}

}

除了把 Map 换成数组,其他的代码都是一样的。所以我就没再加注释,来看一下效率提

升:

013.%E7%BD%97%E9%A9%AC%E6%95%B0%E5%AD%97%E8%BD%AC%E6%95%B4%E

6%95%B0-20240122105301.png

OK,这次 beat 100% 了,效率提升了一大截。

这里需要注意的是,数组的长度为 128,这是基于 ASCII 码的范围设计的。ASCII 码是一

种字符编码标准,它将英文字符、数字、标点符号等映射到 0-127 的整数上。

当使用字符 int currValue = values[s.charAt(i)] 作为数组索引时,字符实际上被转换为

其对应的 ASCII 值。例如,字符 ‘A’ 对应 ASCII 值 65。

使用 128 大小的数组可以确保直接通过字符的 ASCII 值作为索引来访问数组元素,这样的

访问速度更快。

虽然题目中只用到了 7 个罗马字符,但这样可以确保代码的通用性。这是另外一个非常巧

妙的地方。

总结

这道题的巧妙之处就在于:对于罗马数字来说,把一个小值放在大值的左边,就是做减

法,否则为加法。

013.%E7%BD%97%E9%A9%AC%E6%95%B0%E5%AD%97%E8%BD%AC%E6%95%B4%E

6%95%B0-20240122104623.png

剩下的处理就非常简单了。由于罗马数字的数量非常有限,总共就 7 个,仅含字符 (‘I’,

‘V’, ‘X’, ‘L’, ‘C’, ‘D’, ‘M’),我们也可以通过数组来替代 HashMap,这样的效率会更快一点,

虽然 HashMap 的底层也是数组。但毕竟 HashMap 是对数组的一种封装,加上了链表和红

黑树,包括扩容等操作,所以效率肯定没有直接使用数组来得高。

这道题目所涉及到的 Java 基础知识有:

• HashMap

• 数组

• char 型字符

• for 循环

力扣链接:https://leetcode.cn/problems/roman-to-integer/

开通会员 本次下载免费

所有资料全部免费下载! 推荐用户付费下载获取返佣积分! 积分可以兑换商品!
一键复制 下载文档 联系客服