【每日一题】LeetCode - 整数转罗马数字

在罗马数字系统中,七个不同的符号代表不同的值:

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

罗马数字的表示方式是从最大值开始逐次减去每个符号的值,通过组合这些符号构建最终的表示形式。本文将介绍一个基于贪心策略的解决方案,将整数转换为罗马数字。

解题思路

给定一个整数,我们需要通过罗马数字表示出来。罗马数字的构建规则非常有趣:通常情况下,从较大的数值符号开始,按递减顺序逐步添加符号来表示出整个数。但当数位中以4或9开头时,采用"减法形式"表示------比如4用"IV"而不是"IIII"表示,9则用"IX"而不是"VIIII"。这里,我们需要从高位逐步匹配适合的罗马符号值,并从当前整数中减去该符号对应的数值,直到当前整数变为0。

在此代码实现中,首先定义了一个映射表,按从大到小的顺序列出整数与罗马符号的关系,这样便于直接找到合适的符号。然后,我们从最大的数值符号开始遍历,使用一个 while 循环来处理当前数值。当当前数值大于等于符号所代表的值时,减去该值并将对应的符号附加到结果字符串中。通过不断重复上述过程,我们最终得到完整的罗马数字表示。

示例

以下是几个示例解释:

  • 输入 num = 3749,输出结果为 "MMMDCCXLIX",解释如下:
    • 3000 = "MMM",因为 1000 (M) + 1000 (M) + 1000 (M)
    • 700 = "DCC",因为 500 (D) + 100 © + 100 ©
    • 40 = "XL",因为 50 (L) - 10 (X)
    • 9 = "IX",因为 10 (X) - 1 (I)
  • 输入 num = 58,输出结果为 "LVIII",解释如下:
    • 50 = "L"
    • 8 = "VIII",因为 5 (V) + 1 (I) + 1 (I) + 1 (I)
  • 输入 num = 1994,输出结果为 "MCMXCIV",解释如下:
    • 1000 = "M"
    • 900 = "CM",因为 1000 (M) - 100 ©
    • 90 = "XC",因为 100 © - 10 (X)
    • 4 = "IV",因为 5 (V) - 1 (I)

代码实现

cpp 复制代码
class Solution {
public:
    string intToRoman(int num) {
        string ans;
        vector<pair<int, string>> m = {
            {1000, "M"},
            {900, "CM"},
            {500, "D"},
            {400, "CD"},
            {100, "C"},
            {90, "XC"},
            {50, "L"},
            {40, "XL"},
            {10, "X"},
            {9, "IX"},
            {5, "V"},
            {4, "IV"},
            {1, "I"}
        };
        
        for(auto p : m) {
            while(num >= p.first) {
                num -= p.first;
                ans += p.second;
            }
        }
        return ans;
    }
};

代码解释

  1. 定义罗马数字映射表 :首先,我们使用 vector<pair<int, string>> 来存储每一个可能的数值和相应的罗马字符。这里按数值大小从高到低排序,便于逐步匹配。
  2. 贪心算法构建字符串 :接下来,遍历映射表中的每个 (值, 符号) 对。当输入整数大于等于当前值时,循环执行减去当前值并将相应符号添加到结果字符串。通过这个贪心算法,我们逐步构建最终的罗马数字表示。
  3. 终止条件:当输入整数逐步被减为0时,算法终止,最终字符串即为罗马数字。

时间复杂度与空间复杂度

时间复杂度 :O(1)。虽然存在一个 while 循环嵌套在 for 循环中,但我们处理的是有限数的整数符号对,映射表长度固定。故时间复杂度可以认为是常数时间。

空间复杂度:O(1)。代码只需要常量空间存储罗马数字符号对,以及一个字符串变量用于保存结果,因此空间复杂度为常数。

扩展思路

在不同的语言中实现该方法也相对容易。例如,在 Python 中可以使用类似的方法,也可以采用字典和字符串的拼接来表示相应的转换。需要注意的是,罗马数字规则虽然固定,但在一些特殊情况下仍需仔细考虑,比如在多层循环处理时可能会影响效率。贪心算法适用于此类问题,因为它确保每次选择的是当前情况下最佳的罗马符号。

总结

该解法基于贪心算法思想,通过逐步减去数值并附加罗马符号的方式实现整数到罗马数字的转换。代码清晰、易于理解,且高效处理所有可能的输入整数。总体上,这种方法不仅具有简单的逻辑流,也符合罗马数字的规则,尤其是减法表示法的运用。

相关推荐
王老师青少年编程6 分钟前
2024年信奥赛C++提高组csp-s初赛真题及答案解析(阅读程序第3题)
c++·题解·真题·csp·信奥赛·csp-s·提高组
凡人叶枫33 分钟前
C++中输入、输出和文件操作详解(Linux实战版)| 从基础到项目落地,避坑指南
linux·服务器·c语言·开发语言·c++
CSDN_RTKLIB34 分钟前
使用三方库头文件未使用导出符号情景
c++
zheyutao41 分钟前
字符串哈希
算法
A尘埃1 小时前
保险公司车险理赔欺诈检测(随机森林)
算法·随机森林·机器学习
大江东去浪淘尽千古风流人物2 小时前
【VLN】VLN(Vision-and-Language Navigation视觉语言导航)算法本质,范式难点及解决方向(1)
人工智能·python·算法
rainbow68892 小时前
Linux文件描述符与重定向原理
c++
努力学算法的蒟蒻2 小时前
day79(2.7)——leetcode面试经典150
算法·leetcode·职场和发展
2401_841495642 小时前
【LeetCode刷题】二叉树的层序遍历
数据结构·python·算法·leetcode·二叉树··队列
AC赳赳老秦2 小时前
2026国产算力新周期:DeepSeek实战适配英伟达H200,引领大模型训练效率跃升
大数据·前端·人工智能·算法·tidb·memcache·deepseek