穿越古今:罗马数字与整数的双向翻译指南

188 阅读4分钟

起源

罗马数字的确切起源不是很清楚,但它们显然是基于更早的伊特鲁里亚数字系统发展而来的。随着罗马帝国的扩张,罗马数字也传播到了欧洲各地,并被用于各种官方文件、建筑物标记等场合。尽管现代数学和计算已经普遍采用阿拉伯数字系统,但在钟表表盘、电影版权日期、书序以及一些正式文档的序号等方面,罗马数字仍然被保留下来作为传统符号使用。

image.png

转换

随着阿拉伯数字的引入,罗马数字逐渐被取代,尤其是在数学和科学领域。 阿拉伯数字因其优越性成为了现代世界的主要数字表示法。虽然它们在形式上差异很大,但罗马数字和阿拉伯数字都是用来表示数量的工具,且都在西方文化中有着深远的影响。

人们可以轻松地将罗马数字转换为阿拉伯数字,反之亦然,这使得两者之间存在实际的联系。在力扣上有这么两道题目,今天就让我们来一探究竟。

image.png

问题描述

  1. 整数转罗马数字

    • 给定一个正整数,将其转换为罗马数字表示。
  2. 罗马数字转整数

    • 给定一个罗马数字字符串,将其转换为对应的整数值。

示例

  1. 整数转罗马数字

    • 输入: 1994
    • 输出: "MCMXCIV"
  2. 罗马数字转整数

    • 输入: "MCMXCIV"
    • 输出: 1994

解答思路与代码

  1. 整数转罗马数字:

    1. 定义映射:创建一个映射表,将罗马数字与对应的整数值关联起来。
    2. 分解整数:将整数分解为各个位上的数字。
    3. 构建罗马数字:根据映射表构建罗马数字字符串。
function intToRoman(num) {
  // 定义一个映射表,存储罗马数字与对应的整数值
  // 映射表按照降序排列,以确保在构建罗马数字时优先使用较大的罗马数字
  const map = [
    [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"],
  ];

  // 初始化一个空字符串,用于构建罗马数字
  let roman = "";

  // 遍历映射表
  for (const [value, symbol] of map) {
    // 当当前整数大于等于映射表中的值时
    while (num >= value) {
      // 将对应的罗马数字符号添加到结果字符串中
      roman += symbol;
      // 从整数中减去当前值
      num -= value;
    }
  }

  // 返回构建好的罗马数字字符串
  return roman;
}

映射表的长度是固定的(共13个元素),因此外层循环的次数是固定的。内层循环的次数取决于输入的整数 num 的大小。最大可能的次数是 num / 1(当 num 为 1 时),因为每次循环都会从 num 中减去至少 1。综上所述,最坏情况下的时间复杂度为 O(log N),其中 N 是输入的整数 num。空间复杂度为 O(1)。

  1. 罗马数字转整数:
    1. 定义映射:创建一个映射表,将罗马数字与对应的整数值关联起来。
    2. 遍历字符串:从字符串的末尾开始遍历。
    3. 计算结果:根据字符的值累加结果,处理特殊情况。
function romanToInt(s) {
  const romanValues = {
    I: 1,
    V: 5,
    X: 10,
    L: 50,
    C: 100,
    D: 500,
    M: 1000,
  };

  let result = 0;
  let prevValue = 0;

  for (let i = s.length - 1; i >= 0; i--) {
    const currentValue = romanValues[s[i]];
    if (currentValue < prevValue) {
      // 如果当前值小于前一个值,则从结果中减去当前值
      result -= currentValue;
    } else {
      // 否则,加上当前值
      result += currentValue;
    }
    prevValue = currentValue;
  }

  return result;
}

// 测试示例
console.log(romanToInt("III")); // 输出: 3
console.log(romanToInt("IV")); // 输出: 4
console.log(romanToInt("IX")); // 输出: 9
console.log(romanToInt("LVIII")); // 输出: 58
console.log(romanToInt("MCMXCIV")); // 输出: 1994

这种方法的时间复杂度是 O(n),其中 n 是罗马数字字符串的长度。空间复杂度是 O(1),因为我们只使用了固定数量的额外空间。