力扣第12题:整数转罗马数字
题目描述
罗马数字由七种字符组成:I
(1),V
(5),X
(10),L
(50),C
(100),D
(500)和 M
(1000)。例如,数字 2 写作 II
,即为两个并列的 1。数字 12 写作 XII
,即为 X + II
。数字 27 写作 XXVII
,即为 XX + V + II
。
现代的罗马数字在一些特定的规则下,允许用一些较小的数字放在较大的数字前面表示差值。例如:
- 数字 4 写作
IV
,即V - I
。 - 数字 9 写作
IX
,即X - I
。
给定一个整数,将其转换为罗马数字。
示例
示例 1:
输入: num = 3
输出: "III"
示例 2:
输入: num = 1994
输出: "MCMXCIV"
解释: 1994 = 1000 + 900 + 90 + 4,因此 MCMXCIV 表示 1994。
解题思路
罗马数字的转换可以通过“贪心算法”来完成:从最大值的罗马字符开始匹配,尽可能多地减去当前值,并将对应的罗马数字拼接到结果中,直到整数转换完成。为了实现这一过程,我们首先需要定义罗马数字符号及其对应的数值。通过循环匹配符号并更新输入数字,直到将所有的数字转换为罗马数字。
步骤解析
-
罗马数字符号与数值的映射:将所有的罗马数字及其对应的数值以数组形式存储,并按从大到小的顺序排列,以便从大到小依次匹配。
-
贪心算法:从最高数值开始,逐步减去该数值,并将对应的罗马符号添加到结果字符串中。
-
拼接结果:使用
strcat
函数将罗马符号拼接到结果字符串中,直到所有的数字都转换完毕。
代码实现
#include <stdio.h>
#include <string.h>
char* intToRoman(int num) {
// 定义罗马数字符号及其对应值
char* roman_symbols[] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
int values[] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
// 定义用于存储结果的字符串
static char result[20];
int i = 0;
result[0] = '\0'; // 初始化字符串为空
// 依次匹配每个罗马数字符号
while (num > 0) {
while (num >= values[i]) {
strcat(result, roman_symbols[i]);
num -= values[i];
}
i++;
}
return result;
}
int main() {
int num = 1994;
printf("Roman numeral for %d is: %s\n", num, intToRoman(num)); // 输出: MCMXCIV
return 0;
}
代码解释
-
intToRoman
函数:- 使用两个数组存储罗马数字符号与对应的数值,并确保它们按从大到小的顺序排列,以便每次都能匹配到最大的数值。
- 通过
while
循环,当输入数字num
大于等于当前值时,将该值从num
中减去,并将对应的罗马字符添加到结果字符串中。
-
strcat
函数:- 用于拼接字符串。在每次匹配到罗马数字时,将其符号添加到最终结果中。
-
主函数:
- 测试
intToRoman
函数,并输出对应的罗马数字。
- 测试
优化思路
该算法使用了贪心思想,即每次优先匹配大的数值,并逐步减少输入的数字。由于罗马数字的表示是有限且规则的,该算法的效率很高。时间复杂度为 O(1),因为我们最多需要遍历13个不同的罗马符号,且每个符号的匹配次数是有限的。
总结
这道题通过贪心算法有效地将整数转换为罗马数字。利用符号与数值的对应关系,并结合循环和字符串拼接操作,可以轻松实现题目要求的转换。该算法具有较好的时间和空间复杂度,适用于绝大多数整数转罗马数字的场景。