力扣题目解析--整数转罗马数

题目

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

符号
I1
V5
X10
L50
C100
D500
M1000

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

  • 如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
  • 如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 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 的次方(IXCM)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式

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

示例 1:

输入: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:

输入:num = 58

输出:"LVIII"

解释:

50 = L
 8 = VIII

示例 3:

输入:num = 1994

输出:"MCMXCIV"

解释:

1000 = M
 900 = CM
  90 = XC
   4 = IV

提示:

  • 1 <= num <= 3999

代码展示 

class Solution {
public:
    string intToRoman(int num) {
        std::vector<std::pair<int, std::string>> romanMap = {
            {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"}
        };

        std::string result = "";

        // 使用 while 循环处理整数
        while (num > 0) {
            for (const auto& [value, symbol] : romanMap) {
                if (num >= value) {
                    result += symbol;
                    num -= value;
                    break;
                }
            }
        }

        return result;
    
    }
};

代码逐行解释 

  1. 定义映射关系

    std::vector<std::pair<int, std::string>> romanMap = {
        {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"}
    };
    • 创建一个 vector,其中每个元素是一个 pair,第一个元素是整数值,第二个元素是对应的罗马数字字符串。
  2. 初始化结果字符串

    std::string result = "";
  3. 使用 while 循环处理整数

    while (num > 0) {
        for (const auto& [value, symbol] : romanMap) {
            if (num >= value) {
                result += symbol;
                num -= value;
                break;
            }
        }
    }
    • 使用 while 循环,只要 num 大于 0,就继续处理。
    • 内部使用 for 循环遍历 romanMap,找到第一个小于等于 num 的值。
    • 将对应的罗马数字字符串添加到 result 中。
    • 从 num 中减去对应的整数值。
    • 使用 break 跳出内层循环,继续处理下一个值。
for (const auto& [value, symbol] : romanMap) {
  1. for 循环

    • for 循环用于遍历 romanMap 中的每一个元素。
    • romanMap 是一个 std::vector<std::pair<int, std::string>> 类型的向量。
  2. const auto&

    • const auto& 是一种常用的语法,用于引用当前迭代的元素,避免不必要的复制。
    • const 表示我们不打算修改这些值。
    • auto 让编译器自动推导类型。
    • & 表示我们使用引用,而不是复制。
  3. 结构化绑定

    • [value, symbol] 是结构化绑定的语法。
    • value 和 symbol 分别绑定到 std::pair<int, std::string> 中的第一个和第二个元素。
    • value 绑定到 int 类型的值。
    • symbol 绑定到 std::string 类型的值。

等价的传统写法

如果你不熟悉结构化绑定,可以使用传统的写法来理解:

for (const auto& pair : romanMap) {
    int value = pair.first;
    std::string symbol = pair.second;
    if (num >= value) {
        result += symbol;
        num -= value;
        break;
    }
}

for (const auto& pair : romanMap)

  • for 循环:这是一个范围基的 for 循环,用于遍历 romanMap 中的每一个元素。
  • const auto&
    • const 表示我们不打算修改 pair
    • auto 让编译器自动推导 pair 的类型。
    • & 表示我们使用引用,而不是复制。这样可以提高性能,因为我们不需要每次都复制 pair

2. int value = pair.first;

  • pair.firstpair 是一个 std::pair<int, std::string> 类型的对象。
    • pair.first 是 pair 中的第一个元素,类型为 int
    • 我们将 pair.first 的值赋给 value 变量。

3. std::string symbol = pair.second;

  • pair.secondpair 是一个 std::pair<int, std::string> 类型的对象。
    • pair.second 是 pair 中的第二个元素,类型为 std::string
    • 我们将 pair.second 的值赋给 symbol 变量。

4. if (num >= value)

  • 条件判断:检查当前的 num 是否大于或等于 value
    • 如果 num 大于或等于 value,则进入 if 语句块。

5. result += symbol;

  • 字符串拼接:将 symbol 添加到 result 字符串的末尾。
    • result 是一个 std::string,用于存储最终的罗马数字字符串。

6. num -= value;

  • 减少 num:从 num 中减去 value
    • 这一步是为了处理剩下的部分,以便下一次循环继续处理剩余的值。

7. break;

  • 跳出循环:一旦找到一个匹配的罗马数字并处理完当前部分,跳出内层循环。
    • 这样可以确保每次只处理一个最大的匹配部分,然后继续处理剩余的部分。

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值