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

总结

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

相关推荐
爱编程— 的小李5 分钟前
有序序列合并(c语言)
c语言·算法
云卓SKYDROID7 分钟前
无人机反步滑膜控制算法!
算法·无人机·知识科普·云卓科技·反步滑膜控制算法
云卓科技7 分钟前
无人机之自动控制原理篇
科技·算法·目标检测·机器人·无人机
云卓科技9 分钟前
无人机之集群控制方法篇
科技·算法·无人机·交互·制造
混迹网络的权某10 分钟前
每天一道C语言精选编程题之求数字的每⼀位之和
c语言·开发语言·考研·算法·改行学it·1024程序员节
Curry_Math14 分钟前
LeetCode 热题 100之链表3
算法·leetcode·链表
hn小菜鸡3 小时前
LeetCode 2058.找出临界点之间的最小和最大距离
算法·leetcode·职场和发展
liuyang-neu3 小时前
力扣 简单 70.爬楼梯
java·算法·leetcode
IronmanJay3 小时前
【LeetCode每日一题】——862.和至少为 K 的最短子数组
数据结构·算法·leetcode·前缀和·双端队列·1024程序员节·和至少为 k 的最短子数组
OT.Ter3 小时前
【力扣打卡系列】二分查找(搜索旋转排序数组)
算法·leetcode·职场和发展·go·二分查找