题干:
罗马数字包含以下七种字符: I
, V
, X
, L
,C
,D
和 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 到 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、先用map集合将罗马数字标识与整数对应值一一存储起来。
2、再从高位到低位(千位~个位)依次将整数转换罗马。
3、考虑边界和特殊数字(4和9)的转换.
优点:能详细依次计算出每个位上的转换,扩展后算法任然可用。
缺点:太繁杂,线性时间复杂度高,空间耗用较大。
class Solution {
public String intToRoman(int num) {
String result = "";
if(num <1 || num >3999){
return result;
}
Map dataMap = new HashMap();
dataMap.put(1,"I");
dataMap.put(5,"V");
dataMap.put(10,"X");
dataMap.put(50,"L");
dataMap.put(100,"C");
dataMap.put(500,"D");
dataMap.put(1000,"M");
int g = num%10; //个位
int sw = num/10%10; //十位
int b = num/100%10; //百位
int q = num/1000%10; //千位
//千位
if(q >0){
for(int i=1;i<=q;i++){
result += dataMap.get(1000);
}
}
//百位
if(b >0 ){
if(b == 4){
result += dataMap.get(100);
result += dataMap.get(500);
}else if(b < 4){
for(int i =1;i<=b;i++){
result += dataMap.get(100);
}
}else if(9>b && b>4){
String tmp = dataMap.get(500);
for(int j=6;j<=b;j++){
tmp += dataMap.get(100);
}
result += tmp;
}else if(b ==9){
result += dataMap.get(100);
result += dataMap.get(1000);
}
}
//十位
if(sw >0){
if(sw == 4){
result += dataMap.get(10);
result += dataMap.get(50);
}else if(sw <4){
for(int i=1;i<=sw;i++){
result += dataMap.get(10);
}
}else if(sw<9 && sw>4){
String tmp = dataMap.get(50);
for(int j=6;j<=sw;j++){
tmp += dataMap.get(10);
}
result += tmp;
}else if(sw ==9){
result += dataMap.get(10);
result += dataMap.get(100);
}
}
//个位
if(g > 0){
if(g == 4){
result += dataMap.get(1);
result += dataMap.get(5);
}else if(g<4){
for(int i=1;i<=g;i++){
result += dataMap.get(1);
}
}else if(g<9 && g>4){
String tmp = dataMap.get(5);
for(int j=6;j<=g;j++){
tmp += dataMap.get(1);
}
result += tmp;
}else if(g ==9){
result += dataMap.get(1);
result += dataMap.get(10);
}
}
return result;
}
}
解答二(思路):
1、将所有特殊整点位数的罗马数字和整数,分别用字符串数组和int数组初始化(从大至小)。
2、循环并比较整数int数组与输入需转换目标整数的大小,如果目标>=int[i]则依次减掉目标大于int数组的值,结果字符串拼接对应罗马数字。
优点:线性时间和空间复杂度较低,简洁易读;算法较优。
缺点:如果目标数字过大,并且罗马数字表示负责的话,加大了初始化整数数组和罗马字符数组工作,并易遗漏。
class Solution {
public String intToRoman(int num) {
int values[]={1000,900,500,400,100,90,50,40,10,9,5,4,1};
String reps[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
StringBuffer sb=new StringBuffer();
for(int i=0; i<13; i++){
while(num>=values[i]){
num -= values[i];
sb.append(reps[i]);
}
}
return sb.toString();
}
}
觉得对你有帮助,关注博客和公众号。不定期分享最新前沿技术框架和bat大厂常用技术等,加群不定期分享行业内大牛直播讲课以及获得视频课件资料等。