哈希表题目:整数转罗马数字

题目

标题和出处

标题:整数转罗马数字

出处:12. 整数转罗马数字

难度

3 级

题目描述

要求

罗马数字包含以下七种字符: I \texttt{I} I V \texttt{V} V X \texttt{X} X L \texttt{L} L C \texttt{C} C D \texttt{D} D M \texttt{M} M

字符数值
I \texttt{I} I 1 \texttt{1} 1
V \texttt{V} V 5 \texttt{5} 5
X \texttt{X} X 10 \texttt{10} 10
L \texttt{L} L 50 \texttt{50} 50
C \texttt{C} C 100 \texttt{100} 100
D \texttt{D} D 500 \texttt{500} 500
M \texttt{M} M 1000 \texttt{1000} 1000

例如,罗马数字 2 \texttt{2} 2 写做 II \texttt{II} II,即为两个 1 \texttt{1} 1 相加。 12 \texttt{12} 12 写做 XII \texttt{XII} XII,即为 X   +   II \texttt{X + II} X + II 27 \texttt{27} 27 写做 XXVII \texttt{XXVII} XXVII,即为 XX   +   V   +   II \texttt{XX + V + II} XX + V + II

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 \texttt{4} 4 不写做 IIII \texttt{IIII} IIII,而是 IV \texttt{IV} IV,即数字 1 \texttt{1} 1 在数字 5 \texttt{5} 5 的左边,所表示的数等于 5 \texttt{5} 5 1 \texttt{1} 1 得到的数值 4 \texttt{4} 4。同样地,数字 9 \texttt{9} 9 表示为 IX \texttt{IX} IX。这个特殊的规则只适用于以下六种情况:

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

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

示例

示例 1:

输入: num   =   3 \texttt{num = 3} num = 3
输出: "III" \texttt{"III"} "III"

示例 2:

输入: num   =   4 \texttt{num = 4} num = 4
输出: "IV" \texttt{"IV"} "IV"

示例 3:

输入: num   =   9 \texttt{num = 9} num = 9
输出: "IX" \texttt{"IX"} "IX"

示例 4:

输入: num   =   58 \texttt{num = 58} num = 58
输出: "LVIII" \texttt{"LVIII"} "LVIII"
解释: L   =   50 \texttt{L = 50} L = 50 V   =   5 \texttt{V = 5} V = 5 III   =   3 \texttt{III = 3} III = 3

示例 5:

输入: num   =   1994 \texttt{num = 1994} num = 1994
输出: "MCMXCIV" \texttt{"MCMXCIV"} "MCMXCIV"
解释: M   =   1000 \texttt{M = 1000} M = 1000 CM   =   900 \texttt{CM = 900} CM = 900 XC   =   90 \texttt{XC = 90} XC = 90 IV   =   4 \texttt{IV = 4} IV = 4

数据范围

  • 1 ≤ num ≤ 3999 \texttt{1} \le \texttt{num} \le \texttt{3999} 1num3999

解法

思路和算法

为了将整数转换成罗马数字,需要从高到低遍历整数的每一位并转换成对应的罗马数字中的符号。

整数的每一位都是 0 0 0 9 9 9,只需要考虑大于 0 0 0 的数位。数位值 1 1 1 5 5 5 都可以用一个字符表示,数位值 2 2 2 3 3 3 6 6 6 7 7 7 8 8 8 都可以用两个至四个字符的加法表示,数位值 4 4 4 9 9 9 都可以用两个字符的减法表示。

对于一个字符表示和多个字符的加法表示,由于每个字符的值不会大于当前数位的值,因此可以直接转换。对于减法表示,由于存在字符的值大于当前数位的值( 4 4 4 的表示为 5 − 1 5 - 1 51 9 9 9 的表示为 10 − 1 10 - 1 101),因此不能直接转换,而是需要引入新的符号。

罗马数字包含 7 7 7 种字符,罗马数字中的减法规则定义了 6 6 6 种复合符号,因此共有 13 13 13 种符号。

符号数值
I \text{I} I 1 1 1
IV \text{IV} IV 4 4 4
V \text{V} V 5 5 5
IX \text{IX} IX 9 9 9
X \text{X} X 10 10 10
XL \text{XL} XL 40 40 40
L \text{L} L 50 50 50
XC \text{XC} XC 90 90 90
C \text{C} C 100 100 100
CD \text{CD} CD 400 400 400
D \text{D} D 500 500 500
CM \text{CM} CM 900 900 900
M \text{M} M 1000 1000 1000

使用上述 13 13 13 种符号,整数中每个数位的每个值对应的罗马数字的表示是唯一的,因此每个整数对应的罗马数字的表示是唯一的。

转换方法是:从大到小依次遍历 13 13 13 种符号对应的数值,对于每个数值,如果当前的 num \textit{num} num 大于或等于该数值,则将当前符号拼接到罗马数字中,并将当前数值从 num \textit{num} num 中减去,直到 num \textit{num} num 小于当前数值,然后对下一个数值继续上述操作,直到 num \textit{num} num 变成 0 0 0

上述转换方法的一种等价做法是:对于每个数值,计算当前的 num \textit{num} num 除以该数值的商(向零取整),即可得到当前符号在罗马数字中的出现次数,将当前符号按照出现次数拼接到罗马数字中,并将 num \textit{num} num 对当前的数值取模,即完成当前符号的拼接,然后对下一个数值继续上述操作,直到 num \textit{num} num 变成 0 0 0

代码

class Solution {
    static final int[] VALUES = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
    static final String[] SYMBOLS = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

    public String intToRoman(int num) {
        StringBuffer sb = new StringBuffer();
        int length = VALUES.length;
        for (int i = 0; i < length; i++) {
            int value = VALUES[i];
            String symbol = SYMBOLS[i];
            int count = num / value;
            for (int j = 0; j < count; j++) {
                sb.append(symbol);
            }
            num %= value;
        }
        return sb.toString();
    }
}

复杂度分析

  • 时间复杂度: O ( 1 ) O(1) O(1)。由于符号的数量固定,因此转换的操作次数固定。

  • 空间复杂度: O ( 1 ) O(1) O(1)。由于符号的数量固定,因此存储对应关系使用的空间固定。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伟大的车尔尼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值