当前位置: 首页 > article >正文

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

题目

罗马数字包含以下七种字符: I, V, X, LCD 和 M

字符          数值
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 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

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

示例 1:

输入: s = "III"
输出: 3

示例 2:

输入: s = "IV"
输出: 4

示例 3:

输入: s = "IX"
输出: 9

示例 4:

输入: s = "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.

示例 5:

输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

提示:

  • 1 <= s.length <= 15
  • s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
  • 题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999] 内
  • 题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。
  • IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。
  • 关于罗马数字的详尽书写规则,可以参考 罗马数字 - 百度百科。

代码展示 

#include <unordered_map>
#include<string>
using namespace std;
class Solution {
public:
    int romanToInt(string s) {
        std::unordered_map<char, int> romanMap = {
            {'I', 1}, {'V', 5}, {'X', 10}, {'L', 50},
            {'C', 100}, {'D', 500}, {'M', 1000}
        };
        int sum=0;
        int ret=s.size();
        for (size_t i = 0; i <ret ; ++i) {
            int currentValue = getIntegerValue(s[i], romanMap);
            if (i + 1 < s.length()) {
                int nextValue = getIntegerValue(s[i + 1], romanMap);
                if (currentValue < nextValue) {
                    sum += nextValue - currentValue;
                    ++i; // 跳过下一个字符
                } else {
                    sum += currentValue;
                }
            } else {
                sum += currentValue;
            }
        }
        return sum;
    }
    private:
    int getIntegerValue(char romanchar,const unordered_map<char, int>&map){
    auto it=map.find(romanchar);
    if(it!=map.end()){
        return it->second;
    }else{
        return 0;
    }
}

};

代码解释 

  1. romanToInt 方法

    • std::unordered_map<char, int> romanMap:创建一个无序映射表,存储罗马数字字符及其对应的整数值。
    • int sum = 0:初始化总和为0。
    • int ret = s.size():获取输入字符串的长度。
    • for (size_t i = 0; i < ret; ++i):遍历字符串中的每一个字符。
    • int currentValue = getIntegerValue(s[i], romanMap):获取当前字符对应的整数值。
    • if (i + 1 < s.length()):检查是否还有下一个字符。
    • int nextValue = getIntegerValue(s[i + 1], romanMap):获取下一个字符对应的整数值。
    • if (currentValue < nextValue):如果当前字符的值小于下一个字符的值,说明这是一个减法情况。
    • sum += nextValue - currentValue:计算减法结果并添加到总和中。
    • ++i:跳过下一个字符。
    • else:否则,直接加上当前字符的值。
    • else:如果已经是最后一个字符,直接加上其值。
    • return sum:返回计算结果。
  2. getIntegerValue 方法

    • auto it = map.find(romanchar):在映射表中查找给定字符。
    • if (it != map.end()):如果找到了对应的值,返回该值。
    • else:如果没有找到对应的值,返回0。

   3. 辅助函数 getIntegerValue

int getIntegerValue(char romanChar, const std::unordered_map<char, int>& map) {
    auto it = map.find(romanChar);
    if (it != map.end()) {
        return it->second;
    }
    return 0; // 如果找不到,返回 0
}

详细解释

  1. 函数签名

    int getIntegerValue(char romanChar, const std::unordered_map<char, int>& map)
    • int getIntegerValue:函数返回一个整数值。
    • char romanChar:函数接受一个字符参数,表示罗马数字字符。
    • const std::unordered_map<char, int>& map:函数接受一个常量引用参数,表示映射表。std::unordered_map<char, int> 是一个哈希表,键是字符,值是整数。
  2. 查找字符

    auto it = map.find(romanChar);
    • map.find(romanChar):在映射表 map 中查找键为 romanChar 的元素。
    • auto it:使用 auto 关键字自动推导 it 的类型。it 是一个迭代器,指向找到的元素。
  3. 检查是否找到

    if (it != map.end()) {
        return it->second;
    }
    • if (it != map.end()):检查迭代器 it 是否不等于 map.end()map.end() 是一个特殊迭代器,表示映射表的结束位置。
    • 如果 it 不等于 map.end(),说明找到了键为 romanChar 的元素。
    • return it->second:返回找到的元素的值。it->second 表示迭代器 it 指向的键值对中的值。
  4. 未找到时返回 0

    return 0; // 如果找不到,返回 0
    • 如果 it 等于 map.end(),说明没有找到键为 romanChar 的元素。
    • 返回 0,表示未找到对应的整数值。

示例解释

假设我们有一个映射表 romanMap

std::unordered_map<char, int> romanMap = {
    {'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000}
};
示例调用
  1. 调用 getIntegerValue('I', romanMap)

    • map.find('I') 返回一个迭代器,指向键为 'I' 的元素。
    • it->second 是 1。
    • 返回 1。
  2. 调用 getIntegerValue('V', romanMap)

    • map.find('V') 返回一个迭代器,指向键为 'V' 的元素。
    • it->second 是 5。
    • 返回 5。
  3. 调用 getIntegerValue('Z', romanMap)

    • map.find('Z') 返回 map.end(),因为 'Z' 不在映射表中。
    • 返回 0。

4.auto it 和迭代器的具体使用方法

迭代器的概念

在 C++ 中,迭代器是一种通用的概念,用于遍历容器中的元素。迭代器的行为类似于指针,可以用来访问和操作容器中的元素。不同的容器(如 std::vectorstd::liststd::unordered_map 等)有不同的迭代器类型。

std::unordered_map 的迭代器

std::unordered_map 是一个哈希表,它的迭代器类型是 std::unordered_map<K, V>::iteratorstd::unordered_map<K, V>::const_iterator,具体取决于你是否需要修改映射表中的元素。

迭代器的成员
  • it->first:访问键(key)。
  • it->second:访问值(value)。

auto 关键字

auto 关键字用于自动推导变量的类型。在 auto it = map.find(romanChar); 中,编译器会根据 map.find(romanChar) 的返回类型自动推导 it 的类型。在这种情况下,it 的类型是 std::unordered_map<char, int>::iterator

使用迭代器的注意事项

  1. 检查迭代器的有效性

    • 在使用迭代器之前,必须确保它有效。通常通过检查迭代器是否等于 map.end() 来判断是否找到了元素。
    • 示例:
      auto it = map.find(romanChar);
      if (it != map.end()) {
          // 找到了元素
      } else {
          // 没有找到元素
      }
  2. 避免越界

    • 不要试图访问超出容器范围的元素。例如,不要在迭代器等于 map.end() 时访问 it->second
    • 示例:
      auto it = map.find(romanChar);
      if (it != map.end()) {
          int value = it->second; // 安全访问
      }
  3. 修改元素

    • 如果你使用的是非常量迭代器(std::unordered_map<K, V>::iterator),可以通过迭代器修改值。
    • 示例:
      auto it = map.find(romanChar);
      if (it != map.end()) {
          it->second = 10; // 修改值
      }
  4. 迭代器失效

    • 在某些操作(如插入、删除)之后,迭代器可能会失效。使用迭代器时要确保它仍然有效。
    • 示例:
      auto it = map.find(romanChar);
      if (it != map.end()) {
          int value = it->second;
          // 插入新元素后,it 仍然有效
          map.insert({'A', 1});
          // 删除元素后,it 可能失效
          map.erase(romanChar);
      }

 

总结 

其实罗马数字转换为整型这个问题并没有这样复杂,只是我在做题目的过程中想要利用一下函数和使用一下自定义的函数,才会显得这个代码有些臃肿和复杂。我最初的想法就是通过映射表来处理罗马数字和整数之间的关系,只是在推进的过程之中。我发现要解决这个问题就需要自定义一个函数去专门的在映射表之中寻找罗马数字和整型数字,因此就定义了一个这样的函数去通过罗马数字寻找整数,而在我已经完成这个函数,并且。得到结果的时候我发现罗马数字有一个很关键的问题就是。数字小的时候,有可能会把数字大的放在后头,类似于罗马数字四-----IV,这样子就不能只通过直接读取字符串来简单地进行加得到整数。如果没有这样的特性,我认为映射表应该是更简单的。但是正是因为这样的特性造成了原本优秀的想法反倒吃了瘪,进而造成了代码的臃肿。


http://www.kler.cn/a/378444.html

相关文章:

  • 【算法】【优选算法】双指针(下)
  • 【点云学习笔记】——分割任务学习
  • AI大模型如何重塑软件开发流程
  • 气象大模型学习笔记
  • Docker可视化管理面板DPanel的安装
  • C++线程异步
  • 一次明白——Vue.js组件开发!
  • Kubernetes运行大数据组件-运行spark
  • element plus中修改el-table的样式
  • JAVA语言多态和动态语言实现原理
  • 深度学习:反向传播算法简介
  • 一体化运维监控管理平台详解:构建高效运维体系
  • 如何通过OpenAI Gym学习强化学习
  • 乡村景区一体化系统(门票,餐饮,便利店,果园,娱乐,停车收费
  • 两个壁面之间夹一个圆柱形杆的温度分布
  • LeetCode 684.冗余连接:拓扑排序+哈希表(O(n)) 或 并查集(O(nlog n)-O(nα(n)))
  • 使用GetX实现GetPage中间件
  • WordPress在windows下安装
  • 【Git】从 GitHub 仓库中移除误提交的 IntelliJ IDEA 配置文件夹 .idea 并将其添加到 .gitignore 文件中
  • MyBatis-Plus快速入门:从安装到第一个Demo
  • React Native 0.76 重大更新:新架构全面启用
  • 基于Python的自然语言处理系列(47):DistilBERT:更小、更快、更省、更轻的BERT版本
  • C++编程法则365天一天一条(344)理解std::optional的设计初衷
  • 数据库日志分析 ApexSQLLog
  • 基于SSM+VUE历史车轮网站JAVA|VUE|Springboot计算机毕业设计源代码+数据库+LW文档+开题报告+答辩稿+部署教+代码讲解
  • Zypher Network:全栈式 Web3 游戏引擎,服务器抽象叙事的领导者