LeetCode【0012】整数转罗马数字

本文目录

  • [1 中文题目](#1 中文题目)
  • [2 求解思路](#2 求解思路)
    • [2.1 基础解法:除法取余法](#2.1 基础解法:除法取余法)
    • [2.2 优化解法:模式匹配法](#2.2 优化解法:模式匹配法)
    • [2.3 最优解法:硬编码法](#2.3 最优解法:硬编码法)
  • [3 题目总结](#3 题目总结)

1 中文题目

七个不同的符号代表罗马数字,其值如下:

符号
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:

  • 如果该值不是以 49 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
  • 如果该值以 49 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)
  • 只有 10 的次方(I, X, C, M)最多可以连续附加 3 次以代表 10 的倍数。不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式

给定一个整数,将其转换为罗马数字。
示例 1:

python 复制代码
输入:num = 3749
输出: "MMMDCCXLIX"
解释:
3000 = MMM 由于 1000 (M) + 1000 (M) + 1000 (M)
 700 = DCC 由于 500 (D) + 100 (C) + 100 (C)
  40 = XL 由于 50 (L) 减 10 (X)
   9 = IX 由于 10 (X) 减 1 (I)
注意:49 不是 50 (L) 减 1 (I) ,因为转换是基于小数位

示例 2:

python 复制代码
输入:num = 58
输出:"LVIII"
解释:
50 = L
8 = VIII

示例 3:

python 复制代码
输入:num = 1994
输出:"MCMXCIV"
解释:
1000 = M
 900 = CM
  90 = XC
   4 = IV

提示:

  • 1 ≤ n u m ≤ 3999 1\leq num \leq 3999 1≤num≤3999

2 求解思路

2.1 基础解法:除法取余法

思路

将数字按位分解(千位、百位、十位、个位),对每个位置上的数字分别处理,根据不同位置的权重选择对应的罗马数字字符,最后将所有位置的结果组合。

详细算法步骤:

  • 千位处理(1000-3000):
    • 除以1000获取千位数字,重复相应次数的M
  • 百位处理(100-900):
    • 对1000取余后除以100获取百位数字
    • 根据数值选择处理方式:
      • 900:使用CM
      • 500-800:使用D加若干个C
      • 400:使用CD
      • 100-300:使用若干个C
  • 十位处理(10-90):
    • 对100取余后除以10获取十位数字
    • 根据数值选择处理方式:
      • 90:使用XC
      • 50-80:使用L加若干个X
      • 40:使用XL
      • 10-30:使用若干个X
  • 个位处理(1-9):
    • 对10取余获取个位数字
    • 根据数值选择处理方式:
      • 9:使用IX
      • 5-8:使用V加若干个I
      • 4:使用IV
      • 1-3:使用若干个I

python代码

python 复制代码
class Solution:
    def intToRoman(self, num: int) -> str:
        """
        使用除法取余法将整数转换为罗马数字
        
        参数:
            num: 1-3999范围内的整数
        返回:
            对应的罗马数字字符串
        """
        result = ''
        
        # 处理千位(1000-3000)
        # 千位最大到3,直接重复M即可
        thousands = num // 1000
        result += 'M' * thousands
        
        # 处理百位(100-900)
        hundreds = (num % 1000) // 100
        if hundreds == 9:
            # 900 使用 CM 表示
            result += 'CM'
        elif hundreds >= 5:
            # 500-800 使用 D 加若干个 C 表示
            result += 'D' + 'C' * (hundreds - 5)
        elif hundreds == 4:
            # 400 使用 CD 表示
            result += 'CD'
        else:
            # 100-300 使用若干个 C 表示
            result += 'C' * hundreds
            
        # 处理十位(10-90)
        tens = (num % 100) // 10
        if tens == 9:
            # 90 使用 XC 表示
            result += 'XC'
        elif tens >= 5:
            # 50-80 使用 L 加若干个 X 表示
            result += 'L' + 'X' * (tens - 5)
        elif tens == 4:
            # 40 使用 XL 表示
            result += 'XL'
        else:
            # 10-30 使用若干个 X 表示
            result += 'X' * tens
            
        # 处理个位(1-9)
        ones = num % 10
        if ones == 9:
            # 9 使用 IX 表示
            result += 'IX'
        elif ones >= 5:
            # 5-8 使用 V 加若干个 I 表示
            result += 'V' + 'I' * (ones - 5)
        elif ones == 4:
            # 4 使用 IV 表示
            result += 'IV'
        else:
            # 1-3 使用若干个 I 表示
            result += 'I' * ones
            
        return result

时空复杂度分析

  • 时间复杂度分析:O(1):固定的四个位置处理
  • 空间复杂度分析:O(1):使用固定大小的空间

2.2 优化解法:模式匹配法

思路

观察罗马数字的规律,发现其遵循特定模式:当较小的罗马数字出现在较大的罗马数字左边时表示减法,右边时表示加法。基于这个规则,我们可以从大到小构建一个模式表,然后通过重复匹配和替换来构建罗马数字。

详细算法步骤:

  • 准备模式映射表:
    • 包含所有基本数值和特殊组合(如4、9等)
    • 按数值从大到小排序
    • 每个模式包含数值和对应的罗马数字符号
  • 遍历处理过程:
    • 从最大的模式开始遍历
    • 对每个模式,重复执行:
      • 检查当前数字是否大于等于模式值
      • 如果是,追加对应的罗马数字符号
      • 从输入数字中减去已处理的值
  • 直到当前数字小于模式值
  • 继续处理下一个模式
  • 当数字变为0时可以提前结束

python代码

python 复制代码
class Solution:
    def intToRoman(self, num: int) -> str:
        """
        使用模式匹配法将整数转换为罗马数字
        
        参数:
            num: 1-3999范围内的整数
        返回:
            对应的罗马数字字符串
        """
        # 定义数值到罗马数字的模式映射
        # 按从大到小顺序排列,确保优先匹配大的数值
        patterns = [
            (1000, "M"),   # 1000
            (900, "CM"),   # 900 = 1000-100
            (500, "D"),    # 500
            (400, "CD"),   # 400 = 500-100
            (100, "C"),    # 100
            (90, "XC"),    # 90 = 100-10
            (50, "L"),     # 50
            (40, "XL"),    # 40 = 50-10
            (10, "X"),     # 10
            (9, "IX"),     # 9 = 10-1
            (5, "V"),      # 5
            (4, "IV"),     # 4 = 5-1
            (1, "I")       # 1
        ]
        
        # 用于存储结果的罗马数字
        result = ""
        
        # 遍历所有模式
        for value, symbol in patterns:
            # 当前数字大于等于模式值时
            while num >= value:
                # 追加对应的罗马数字符号
                result += symbol
                # 从输入数字中减去已处理的值
                num -= value
                
            # 如果数字已经处理完,提前结束
            if num == 0:
                break
                
        return result

时空复杂度分析

  • 时间复杂度分析:O(1):虽然有循环,但循环次数有上限
  • 空间复杂度分析:O(1):使用固定大小的空间

2.3 最优解法:硬编码法

思路

将数字按位分解,每一位(千位、百位、十位、个位)都有固定的几种罗马数字表示方式,提前将这些映射准备好,然后直接查表拼接得到结果。

Python代码

python 复制代码
class Solution:
    def intToRoman(self, num: int) -> str:
        """
        将整数转换为罗马数字
        
        参数:
            num: 1-3999范围内的整数
        返回:
            对应的罗马数字字符串
        """
        # 千位数字的罗马数字表示(1000, 2000, 3000)
        thousands = ["", "M", "MM", "MMM"]
        
        # 百位数字的罗马数字表示(100到900)
        hundreds = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"]
        
        # 十位数字的罗马数字表示(10到90)
        tens = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"]
        
        # 个位数字的罗马数字表示(1到9)
        ones = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"]
        
        # 分解数字,获取每一位的值
        # 例如:1994
        # thousand_digit = 1
        # hundred_digit = 9
        # ten_digit = 9
        # one_digit = 4
        thousand_digit = num // 1000  # 取千位
        hundred_digit = (num % 1000) // 100  # 取百位
        ten_digit = (num % 100) // 10  # 取十位
        one_digit = num % 10  # 取个位
        
        # 拼接结果
        # 直接从对应位置的数组中获取罗马数字表示
        # 例如:1994 = M + CM + XC + IV
        return thousands[thousand_digit] + hundreds[hundred_digit] + tens[ten_digit] + ones[one_digit]

时空复杂度分析

  • 时间复杂度分析:O(1):因为所有操作都是常数时间
  • 空间复杂度分析:O(1):使用固定大小的数组存储映射关系

3 题目总结

题目难度:中等
数据类型:整数
应用算法:基于规则

相关推荐
DdddJMs__1353 分钟前
C语言 | Leetcode C语言题解之第552题学生出勤记录II
c语言·leetcode·题解
DdddJMs__1357 分钟前
C语言 | Leetcode C语言题解之第554题砖墙
c语言·leetcode·题解
AI原吾15 分钟前
探索Python的HTTP利器:Requests库的神秘面纱
python·requests
灰哥数据智能21 分钟前
DB-GPT系列(五):DB-GPT六大基础应用场景part2
数据库·人工智能·python·sql·gpt·abi
微学AI21 分钟前
MathGPT的原理介绍,在中小学数学教学的应用场景,以及代码样例实现
人工智能·python·大模型·mathgpt
小馒头学python22 分钟前
机器学习中的分类:决策树、随机森林及其应用
人工智能·python·决策树·随机森林·机器学习·分类
weixin_4786897637 分钟前
【121. 买卖股票的最佳时机】——贪心算法/动态规划
算法·贪心算法·动态规划
武昌库里写JAVA1 小时前
mysql 几种启动和关闭mysql方法介绍
java·开发语言·算法·spring·log4j
B站计算机毕业设计超人1 小时前
计算机毕业设计Python+Neo4j知识图谱医疗问答系统 大模型 机器学习 深度学习 人工智能 大数据毕业设计 Python爬虫 Python毕业设计
爬虫·python·深度学习·机器学习·知识图谱·课程设计·neo4j
我是聪明的懒大王懒洋洋1 小时前
力扣力扣力:53.最大子数组和
算法·leetcode·职场和发展