• 【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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    例如, 罗马数字 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
    
    • 1
    • 2

    示例 2:

    输入: s = "IV"
    输出: 4
    
    • 1
    • 2

    示例 3:

    输入: s = "IX"
    输出: 9
    
    • 1
    • 2

    示例 4:

    输入: s = "LVIII"
    输出: 58
    解释: L = 50, V= 5, III = 3.
    
    • 1
    • 2
    • 3

    示例 5:

    输入: s = "MCMXCIV"
    输出: 1994
    解释: M = 1000, CM = 900, XC = 90, IV = 4.
    
    • 1
    • 2
    • 3

    提示:

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

    方案1:暴力解

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

    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;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

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

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

    方案2

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

    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;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36

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

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

    方案3

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

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

    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;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

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

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

  • 相关阅读:
    tk_mapper 代码生成
    17-GuliMall 搭建虚拟域名访问环境
    Elasticsearch最详细集群环境搭建
    如何做好测试?(二)单元测试(Unit Testing, UT)
    用java实现学生成绩管理系统(附有详细代码)
    数据结构 | 顺序表
    Kubernetes Namespace
    python PyQt5(自定义)信号与槽详解与实例
    AVR单片机与C语言的一些入门简要概述
    数据结构(时间复杂度,空间复杂度)
  • 原文地址:https://blog.csdn.net/Slience_me/article/details/134523502