力扣---12. 整数转罗马数字____以及一些对于auto的说明

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

符号
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

做法1.总结来说就是把题目的限制条件,全部使用if-else进行限制,然后往字符串后端添加相对应的字母即可。这种做法的优点就是节省内存,但是运行时间比较长。时间较短的方法可看做法2。该做法更加容易看懂,初学方法。

class Solution {
public:
    string intToRoman(int num) {
        string res="";
        int temp = num,C_s = 1000;
        while(temp){
            int temp_res = temp / C_s;
            int te = temp_res;
            if(temp_res){
                if(C_s==1000){
                    while(temp_res){
                        res += "M";
                        temp_res--;
                    }
                }else if(C_s==100){
                    if(temp_res==9){
                        res += "CM";
                    }else if(temp_res==4){
                        res += "CD";
                    }else if(temp_res >= 5){
                        res += "D";
                        temp_res -= 5;
                        while(temp_res){
                            res += "C";
                            temp_res--;
                        }
                    }else if(temp_res){
                        while(temp_res){
                            res += "C";
                            temp_res--;
                        }
                    }
                }else if(C_s==10){
                    if(temp_res==9){
                        res += "XC";
                    }else if(temp_res==4){
                        res += "XL";
                    }else if(temp_res >= 5){
                        res += "L";
                        temp_res -= 5;
                        while(temp_res){
                            res += "X";
                            temp_res--;
                        }
                    }else if(temp_res){
                        while(temp_res){
                            res += "X";
                            temp_res--;
                        }
                    }
                }else if(C_s==1){
                    if(temp_res==9){
                        res += "IX";
                    }else if(temp_res==4){
                        res += "IV";
                    }else if(temp_res >= 5){
                        res += "V";
                        temp_res -= 5;
                        while(temp_res){
                            res += "I";
                            temp_res--;
                        }
                    }else if(temp_res){
                        while(temp_res){
                            res += "I";
                            temp_res--;
                        }
                    }
                }
            }
            temp -= te * C_s;
            C_s /=10;
        }
        return res;
    }
};

做法2.

vector<pair<int, string>>

这里先解释一下上面这行代码:

  1. pair 是 C++ 标准库中的一种模板类,用于存储两个相关联的值。这两个值可以是不同类型。这号符合题目中的键值条件。
  2. vector 是 C++ 标准库中的模板类,表示动态数组,可以调整其大小并允许在任意位置快速访问元素。
class Solution {
public:
    string intToRoman(int num) {
         // 罗马数字及其对应的数值
        vector<pair<int, string>> roman = {
            {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"}
        };
    
        string result;
        
        // 遍历罗马数字表
        for (const auto& [value, symbol] : roman) {
            while (num >= value) {
                result += symbol;
                num -= value;
            }
        }
        
        return result;
    }
};

另一个需要注意的就是

for (auto [value, symbol] : roman) 

这里直接使用auto也对,但是会出现警告,所以就咨询了一下chatgpt,其给出的原因就是:

  1. 避免复制

    • 当你遍历一个包含复杂对象(例如 pair<int, string>)的容器时,如果不使用引用而是直接使用值(auto),会导致每次迭代都进行一次复制操作。复制复杂对象是昂贵的,尤其是在对象包含动态分配的资源时,例如 string
    • 使用 const auto& 避免了这种复制,直接引用容器中的元素,提高了性能。
  2. 保护数据

    • 使用 const 确保在循环内部不会修改容器中的元素。这不仅增加了代码的安全性,还使意图更加明确:你只读取数据而不修改它。
    • 这对于读操作特别有用,因为它防止了意外的修改,增加了代码的可读性和维护性。
  3. 类型推导

    • auto 关键字让编译器自动推导变量的类型,减少了代码的冗长和出错的机会。特别是在处理复杂类型(如 pair<int, string>)时,auto 使代码更加简洁。

其中auto:让编译器推导变量的类型。

这里急着下班了,不解释了,就直接让chatgpt给出对于auto的解释。

auto 是 C++ 中的一种类型推导关键字,它允许编译器根据初始化表达式的类型自动推导变量的类型。这在编写代码时提供了更大的简洁性和灵活性。以下是关于 auto 的详细介绍以及在具体场景中使用 auto 的原因。

auto 的基本用法

  1. 基本示例

    int x = 10;
    auto y = x; // y 的类型是 int
    

  2. 复杂类型的推导

    vector<pair<int, string>> vec;
    auto p = make_pair(1, "example"); // p 的类型是 pair<int, string>
    vec.push_back(p);
    

  3. 迭代器类型

    vector<int> vec = {1, 2, 3, 4};
    auto it = vec.begin(); // it 的类型是 vector<int>::iterator
    

使用 auto 的原因

  1. 简化代码

    vector<pair<int, string>> vec;
    auto it = vec.begin(); // 避免写成 vector<pair<int, string>>::iterator it = vec.begin();
    

  2. 提高可读性

    for (auto it = vec.begin(); it != vec.end(); ++it) {
        // 使用 auto 使得代码更易读
    }
    

  3. 避免重复

    vector<int> vec = {1, 2, 3};
    auto x = vec[0]; // 不需要再次说明 x 的类型是 int
    

  4. 类型一致性

    auto result = some_function(); // result 的类型完全与 some_function() 的返回类型一致
    

  • 25
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值