法一,暴力双for循环,再嵌套if语句
1)代码展示
class Solution {
public:
int romanToInt(string s)
{
int numbers[7] = {1, 5, 10, 50, 100, 500, 1000}; // 数字数组
char letter[7] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'}; // 罗马数字符号数组
int result = 0;
int len = s.length();
for (int i = 0; i < len; i++)
{
int current_value = 0;
int next_value = 0;
// 查找当前字符的数值
for (int j = 0; j < 7; j++)
{
if (s[i] == letter[j])
{
current_value = numbers[j];
break;
}
}
// 查找下一个字符的数值(如果有)
if (i < len - 1) { // 确保 i + 1 不越界
for (int j = 0; j < 7; j++)
{
if (s[i + 1] == letter[j])
{
next_value = numbers[j];
break;
}
}
}
// 根据当前和下一个字符的值决定加或减
if (current_value < next_value)
{
result -= current_value; // 当前值小于下一个值时,执行减法
}
else
{
result += current_value; // 否则执行加法
}
}
return result;
}
};
2) 关键:
a,先构建两个列表来储存数据,方便for循环访问。
b,用.length() 函数来测量列表的长度,而不用strlen()函数,原因是在 C++ 中,strlen
函数是用于处理 C 风格字符串的,即字符数组或者 const char*
类型的字符串。如果你在代码中使用了 C++ 的 std::string
类型,而不是 C 风格的字符串,那么你不能直接将 std::string
传递给 strlen
函数。这里题目提供的函数传入的是std::string类型。
下面是AI提供的它们的区别:
总结表:
特点 | C 风格字符串 (char* ) | std::string (C++ 类) |
---|---|---|
定义 | 基于字符数组,char* 或 const char* | C++ 标准库中的字符串类 |
内存管理 | 手动管理,容易出错 | 自动管理,灵活 |
操作复杂度 | 使用库函数,如 strlen() 、strcpy() | 直接使用成员函数和操作符 |
安全性 | 易发生缓冲区溢出等问题 | 自动扩展,安全性更高 |
长度计算 | 通过 strlen() | 使用 length() 或 size() |
性能 | 可能更高(不涉及动态分配) | 较安全,可能有动态分配开销 |
互操作性 | 可与 std::string 转换 | 可通过 c_str() 获取 C 风格字符串 |
扩展性 | 固定长度,无法扩展 | 动态扩展,灵活 |
c,current value和next value的初始化必须放在for循环内部,使其生命周期只在循环中,才不会后面返回值的时候返回0.
d,用break控制语句来提前结束内嵌的for循环,避免多余的运算。
4)成果展示
二,法二,哈希表法
1)代码展示:
class Solution {
public:
int romanToInt(string s)
{
std::unordered_map<char,int>map{{'I', 1}, {'V', 5}, {'X', 10}, {'L', 50},
{'C', 100}, {'D', 500}, {'M', 1000}};
int result = 0;
int len = s.length();
for(int i = 0;i < len;i++)
{
if(i < len - 1 && map[s[i]] < map[s[i + 1]])
{
result -= map[s[i]];
}
else
{
result += map[s[i]];
}
}
return result;
}
};
2)原理
基本上与第一种相同,区别在创建一个字母和数值的映射,后面查找时直接通过键来找值,没有了比较环节。
3)关键
a,哈希表的创建,注意里面参数的类型,不要像我把char弄成string数据类型
4)成果展示
我不清楚为什么第一种还要优于第二种方法。