LeetCode 13 Roman to Integer (Tag:Hash Table Difficulty:Easy)

203 阅读2分钟

这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

前言

关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!

题目描述

罗马数字包含以下七种字符: I, V, X, LCD 和 M

image.png 给定一个罗马数字,将其转换成整数。

示例 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.

链接:leetcode-cn.com/problems/ro…

题解

这道题目和 leetcode 12 是相反的,上一道题目是将阿拉伯数字转换为罗马数字,这道题目是将罗马数字转换为阿拉伯数字。本质来说,采用的方法都是 hash,将阿拉伯数字和罗马数字映射在一起。

这道题难的地方在于如果我们只是单纯的将罗马数字映射为阿拉伯数字加起来,会出现问题,因为 IV 是两个字符表示一个数字,所以我们在每次加之前或者加之后,需要额外判断后一个数字是不是比当前的数字大,用来纠正 4 9 ... 这些特殊字符的表达问题。

具体代码如下,时间复杂度为 O(n)

/**
 * @param {string} s
 * @return {number}
 */
var romanToInt = function(s) {
    let ans = 0
    const n = ans.length
    const m = {
        'I' : 1, 
        'V': 5, 
        'X': 10, 
        'L' : 50,
        'C' : 100, 
        'D': 500, 
        'M': 1000
    }
    for (let i = 0; i < n; i++) {
        ans += m[s[i]]
        // 判断后一个元素和当前元素的大小
        if (i > 0 && m[s[i]] > m[s[i - 1]]) {
            // 减去两倍是因为前面加了一次
            ans -= 2 * m[s[i - 1]]
        }
    }
    return ans 
};

这道题目还可以从右到左遍历相加,当左边的数比当前数小时,也可以得出需要减去前面的数的结论。本质来说和上面的方法区别不太大,所以不再写出来了。