题目

整数转罗马数字 - 图1

解题思路

罗马数字符号介绍

罗马数字由 77 个不同的单字母符号组成,每个符号对应一个具体的数值。此外,减法规则(如问题描述中所述)给出了额外的 66 个复合符号。这给了我们总共 1313 个独特的符号(每个符号由 11 个或 22 个字母组成),如下图所示。

整数转罗马数字 - 图2

罗马数字的唯一表示法

让我们从一个例子入手。考虑 140的罗马数字表示,下面哪一个是正确的?

整数转罗马数字 - 图3

我们用来确定罗马数字的规则是:对于罗马数字从左到右的每一位,选择尽可能大的符号值。对于 140,最大可以选择的符号值为 C=100。接下来,对于剩余的数字 40,最大可以选择的符号值为 XL=40。因此,140 的对应的罗马数字为 C+XL=CXL。

结合题目

整数转罗马数字 - 图4

回顾上述中列出的这 13个符号,可以发现:

  • 千位数字只能由M表示
  • 百位数字只能由C,CD,D 和 CM 表示
  • 十位数字只能由 X,XL,L 和XC 表示
  • 个位数字只能由 I,IV,V 和 IX 表示。

这恰好把这 13 个符号分为四组,且组与组之间没有公共的符号。因此,整数 num 的十进制表示中的每一个数字都是可以单独处理的。

进一步地,我们可以计算出每个数字在每个位上的表示形式,整理成一张硬编码表。如下图所示,其中 0 对应的是空字符串。

整数转罗马数字 - 图5

利用模运算和除法运算,我们可以得到 num 每个位上的数字:

  1. thousands_digit = num / 1000
  2. hundreds_digit = (num % 1000) / 100
  3. tens_digit = (num % 100) / 10
  4. ones_digit = num % 10

代码

  1. class Solution {
  2. String[] thousands = {"", "M", "MM", "MMM"};
  3. String[] hundreds = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
  4. String[] tens = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
  5. String[] ones = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
  6. public String intToRoman(int num) {
  7. StringBuffer roman = new StringBuffer();
  8. roman.append(thousands[num / 1000]);
  9. roman.append(hundreds[num % 1000 / 100]);
  10. roman.append(tens[num % 100 / 10]);
  11. roman.append(ones[num % 10]);
  12. return roman.toString();
  13. }
  14. }