今日算法之_27_整数转罗马数字
前言
Github:https://github.com/HealerJean
1、整数转罗马数字
罗马数字包含以下七种字符:
I
,V
,X
,L
,C
,D
和M
。2 写做
II
,即为两个并列的 1。12 写做
XII
,即为X + II
。27 写做 ` XXVII
, 即为
XX + V + II`。
字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
通常情况下,罗马数字中小的数字在大的数字的右边 但也存在特例,
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。
示例 1:
输入: 3
输出: "III"
示例 2:
输入: 4
输出: "IV"
示例 3:
输入: 9
输出: "IX"
示例 4:
输入: 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.
示例 5:
输入: 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.
1.1、解题思路
首先给出“罗马数字”与“阿拉伯数字”的对应关系如下:
罗马数字 | 阿拉伯数字 |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
根据下面的发现规律:“罗马数字”与“阿拉伯数字”其它的对应关系。为此,从头开始举例子,以发现规律:
阿拉伯数字 | 转换规则 | 罗马数字 |
---|---|---|
1 | 直接看表 | I |
2 | 2=1+1,相同数字简单叠加 | II |
3 | 3=1+1+1,相同数字简单叠加 | III |
4 | 题目中说的特例:不能写成 4 = 1 + 1 + 1 + 14=1+1+1+1,44 应该看做 4 = 5 - 14=5−1 | IV |
5 | 直接看表 | V |
6 | 6=5+1,大数字在前,小数字在后 | VI |
7 | 7=5+1+1,大数字在前,小数字在后,相同数字简单叠加 | VII |
8 | 8=5+1+1+1,大数字在前,小数字在后,相同数字简单叠加 | VIII |
9 | 题目中说的特例:不能写成 9 = 5 + 1 + 1 + 1 + 19=5+1+1+1+1,99 应该看做 9 = 10 - 19=10−1 | IX |
10 | 直接看表 | X |
出现 4、9、40、90、400、900 的情况比较特殊一些,做的是减法,把它们也加入到“罗马数字”与阿拉伯数字的对应关系表中,并且按照从大到小的顺序排列。
罗马数字 | 阿拉伯数字 |
---|---|
M | 1000 |
CM | 900 |
D | 500 |
CD | 400 |
C | 100 |
XC | 90 |
L | 50 |
XL | 40 |
X | 10 |
IX | 9 |
V | 5 |
IV | 4 |
I | 1 |
1.2、算法
复杂度:
时间复杂度:O(1),虽然看起来是两层循环,但是外层循环的次数是有限制的,因为数字最大才3999,内层循环的此时其实也是有限次的
空间复杂度:O(1),这里使用了两个辅助数字,空间都为 1313,还有常数个变量
public String intToRoman(int num) {
// 把阿拉伯数字与罗马数字可能出现的所有情况和对应关系
//放在两个数组中,按照阿拉伯数字的大小降序排列,因为我们要尽可能的做减法
int[] nums = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
String[] romans = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
int length = nums.length;
StringBuilder stringBuilder = new StringBuilder();
int index = 0;
while (index < length) {
// 这里是等号,这样就保证了那种特殊的数字
while (num >= nums[index]) {
// 注意:这里是等于号,表示尽量使用大的"面值"
stringBuilder.append(romans[index]);
num = num - nums[index];
}
index++;
}
return stringBuilder.toString();
}
1.3、测试
复杂度:
时间复杂度:O(1),虽然看起来是两层循环,但是外层循环的次数是有限制的,因为数字最大才3999,内层循环的此时其实也是有限次的
空间复杂度:O(1)
@Test
public void test(){
System.out.println(intToRoman(11));
}
XI