【Leetcode合集】13. 罗马数字转整数

13. 罗马数字转整数

13. 罗马数字转整数

代码仓库地址https://github.com/slience-me/Leetcode

个人博客https://slienceme.xyz

罗马数字包含以下七种字符: IVXLCDM

复制代码
字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1 。12 写做 XII ,即为 X + II27 写做 XXVII, 即为 XX + V + II

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

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

示例 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 <= s.length <= 15
  • s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
  • 题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999]
  • 题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
  • IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
  • 关于罗马数字的详尽书写规则,可以参考 罗马数字 - Mathematics

方案1:暴力解

使用了哈希表存储数字,然后逐一遍历

cpp 复制代码
class Solution {
public:
    int romanToInt(string s) {
        unordered_map<char, int> myMap = {{'I', 1},
                                          {'V', 5},
                                          {'X', 10},
                                          {'L', 50},
                                          {'C', 100},
                                          {'D', 500},
                                          {'M', 1000}};
        int sum = 0;
        reverse(s.begin(), s.end());
        char this_char = 0;
        char last_char = 0;
        for (int i = 0; i < s.length(); ++i) {
            this_char = s[i];
            if (this_char == 'I' && last_char == 'V') {
                sum -= 1;  // 4 = 5-1
            } else if (this_char == 'I' && last_char == 'X') {
                sum -= 1;  // 9 = 10-1
            } else if (this_char == 'X' && last_char == 'L') {
                sum -= 10; // 40 = 50-10
            } else if (this_char == 'X' && last_char == 'C') {
                sum -= 10; // 90 = 100-10
            } else if (this_char == 'C' && last_char == 'D') {
                sum -= 100; // 400 = 500-100
            } else if (this_char == 'C' && last_char == 'M') {
                sum -= 100; // 900 = 1000-100
            } else {
                sum += myMap[s[i]];
            }
            last_char = this_char;
        }
        return sum;
    }
};

执行用时分布 16ms 击败45.81%使用 C++ 的用户

消耗内存分布8.07MB 击败34.15%使用 C++ 的用户

方案2

初次优化,省去了无用的哈希表,回归本真,字符串本来就可以随机读取,可以直接用\[\]读取,无需存储临时记录

cpp 复制代码
class Solution {
public:
    int romanToInt(string s) {
        int sum = 0;
        for (int i = 0; i < s.length(); ++i) {
            if (s[i] == 'M') {
                sum += 1000;
            } else if (s[i] == 'D') {
                sum += 500;
            } else if (s[i] == 'C') {
                if (s[i + 1] == 'M' || s[i + 1] == 'D') {
                    sum -= 100;
                } else {
                    sum += 100;
                }
            } else if (s[i] == 'L') {
                sum += 50;
            } else if (s[i] == 'X') {
                if (s[i + 1] == 'L' || s[i + 1] == 'C') {
                    sum -= 10;
                } else {
                    sum += 10;
                }
            } else if (s[i] == 'V') {
                sum += 5;
            } else if(s[i] == 'I'){
                if (s[i + 1] == 'X' || s[i + 1] == 'V') {
                    sum -= 1;
                } else {
                    sum += 1;
                }
            }
        }
        return sum;
    }
};

执行用时分布 4ms 击败94.08%使用 C++ 的用户

消耗内存分布 6.21MB 击败71.40%使用 C++ 的用户

方案3

如果当前字符代表的值小于下一个字符代表的值,则减去当前值

最精简但是不是最快的代码

cpp 复制代码
class Solution {
public:
    int romanToInt(string s) {
        unordered_map<char, int> romanMap = {
            {'I', 1},
            {'V', 5},
            {'X', 10},
            {'L', 50},
            {'C', 100},
            {'D', 500},
            {'M', 1000}
        };

        int result = 0;

        for (int i = 0; i < s.length(); ++i) {
            // 如果当前字符代表的值小于下一个字符代表的值,则减去当前值
            if (i + 1 < s.length() && romanMap[s[i]] < romanMap[s[i + 1]]) {
                result -= romanMap[s[i]];
            } else {
                result += romanMap[s[i]];
            }
        }

        return result;
    }
};

执行用时分布 16ms 击败45.81%使用 C++ 的用户

消耗内存分布 8.26MB 击败16.68%使用 C++ 的用户

相关推荐
江畔柳前堤2 小时前
大语言模型分布式训练:从并行策略到万卡工程的系统梳理
人工智能·分布式·深度学习·算法·目标检测·机器学习·语言模型
Forever Nore3 小时前
LeetCode 4 寻找两个正序数组的中位数 - 二分
算法·leetcode
罗西的思考5 小时前
【OpenClaw具身硬件】MiniClaw 阅读笔记---(1)基础
人工智能·算法·机器学习
蛋先生DX5 小时前
大模型参数存储格式揭秘:BF不是男朋友
深度学习·算法·llm
爱跳舞的烤冷面6 小时前
自学嵌入式第22天(数据结构——哈希)
数据结构·算法·哈希算法
猎嘤一号6 小时前
博弈论(Game Theory)的理论、算法与工程
人工智能·算法·安全·博弈论
月光船幽幽6 小时前
影子模式下保护 logits 不被修改
人工智能·python·算法
马拉AI6 小时前
腾讯开源 Agent 记忆系统,AI“换对话就忘”的问题有了新解法(附安装使用教程)
人工智能·算法·开源·科研
地平线开发者8 小时前
征程6工具链模型X86推理方式说明
算法
地平线开发者8 小时前
【征程6】校准量化中HistogramObserver解析
算法