LeetCode 第13题:罗马数字转整数

LeetCode 第13题:罗马数字转整数

题目描述

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

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

  • I:1
  • V:5
  • X:10
  • L:50
  • C:100
  • D:500
  • M:1000

规则说明:

  1. 通常情况下,罗马数字中小的数字在大的数字的右边
  2. 特殊情况(减法规则):
    • IV:4(5-1)
    • IX:9(10-1)
    • XL:40(50-10)
    • XC:90(100-10)
    • CD:400(500-100)
    • CM:900(1000-100)

难度

简单

题目链接

https://leetcode.cn/problems/roman-to-integer/

示例

示例 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] 内
  • 题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况

解题思路

方法一:从左到右扫描

通过观察可以发现一个规律:当小值在大值左边时,需要减去小值;当小值在大值右边或等于大值时,需要加上小值。

关键点:

  1. 将罗马数字映射为对应的数值
  2. 从左到右扫描,比较相邻数字的大小
  3. 根据大小关系决定加减

具体步骤:

  1. 建立罗马数字到整数的映射
  2. 遍历字符串,获取每个字符对应的数值
  3. 比较当前数字与下一个数字:
    • 如果当前数字小于下一个数字,减去当前数字
    • 否则加上当前数字
  4. 最后一个数字一定是加上

时间复杂度:O(n)
空间复杂度:O(1)

方法二:预处理特殊情况

先处理所有的特殊组合(IV、IX等),再处理普通字符。

代码实现

C# 实现(从左到右扫描)

public class Solution {
    private Dictionary<char, int> symbolValues = new Dictionary<char, int> {
        {'I', 1},
        {'V', 5},
        {'X', 10},
        {'L', 50},
        {'C', 100},
        {'D', 500},
        {'M', 1000}
    };
  
    public int RomanToInt(string s) {
        int result = 0;
        int n = s.Length;
      
        for (int i = 0; i < n; i++) {
            int value = symbolValues[s[i]];
            // 如果不是最后一个字符且当前值小于下一个值
            if (i < n - 1 && value < symbolValues[s[i + 1]]) {
                result -= value;
            } else {
                result += value;
            }
        }
      
        return result;
    }
}

C# 实现(预处理特殊情况)

public class Solution {
    private Dictionary<string, int> specialValues = new Dictionary<string, int> {
        {"IV", 4},
        {"IX", 9},
        {"XL", 40},
        {"XC", 90},
        {"CD", 400},
        {"CM", 900}
    };
  
    private Dictionary<char, int> symbolValues = new Dictionary<char, int> {
        {'I', 1},
        {'V', 5},
        {'X', 10},
        {'L', 50},
        {'C', 100},
        {'D', 500},
        {'M', 1000}
    };
  
    public int RomanToInt(string s) {
        int result = 0;
        int i = 0;
      
        while (i < s.Length) {
            // 检查是否是特殊组合
            if (i + 1 < s.Length) {
                string twoChars = s.Substring(i, 2);
                if (specialValues.ContainsKey(twoChars)) {
                    result += specialValues[twoChars];
                    i += 2;
                    continue;
                }
            }
          
            // 处理普通字符
            result += symbolValues[s[i]];
            i++;
        }
      
        return result;
    }
}

代码详解

从左到右扫描版本:

  1. 字符映射:
    • 使用Dictionary存储罗马字符和对应数值
  2. 遍历处理:
    • 获取当前字符的数值
    • 与下一个字符比较大小
    • 根据大小关系决定加减

预处理特殊情况版本:

  1. 特殊组合处理:
    • 预定义所有特殊组合及其值
    • 优先检查是否是特殊组合
  2. 普通字符处理:
    • 如果不是特殊组合,按普通字符处理
    • 直接查表获取数值

执行结果

从左到右扫描版本:

  • 执行用时:76 ms
  • 内存消耗:37.5 MB

预处理特殊情况版本:

  • 执行用时:80 ms
  • 内存消耗:37.8 MB

总结与反思

  1. 这道题的关键点:
    • 理解罗马数字的表示规则
    • 识别特殊情况的处理方法
    • 选择合适的实现策略
  2. 两种解法比较:
    • 从左到右扫描:代码简洁,思路清晰
    • 预处理特殊情况:更直观,但代码较复杂
  3. 优化思路:
    • 使用数组替代Dictionary可能更快
    • 特殊情况的处理可以优化
    • 考虑输入验证

相关题目

posted @   旧厂街小江  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek “源神”启动!「GitHub 热点速览」
· 我与微信审核的“相爱相杀”看个人小程序副业
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 如何使用 Uni-app 实现视频聊天(源码,支持安卓、iOS)
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
点击右上角即可分享
微信分享提示