今天的每日一题还是很简单的,分情况分析就好,只不过我写的比较繁琐,一会看下大佬们的题解学习一下更好的方法,再来更新。新的方法已更新,还有一个编码表的方法没有放上来,因为这些方法之间的区别就是“预处理”的好坏之分,用空间换时间,要达到更好的时间效率,还可以直接==“打表”==,反正只有3999个结果,直接全部打印出来,存到一个数组内,只需要花费查找的时间就可以了(手动狗头)
思路
因为是int数字转化为罗马字符,所以先对几种特殊情况进行处理:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
把上述的情况存在roman2数组内,方便取用。然后把常规的罗马字符放在roman数组内。
因为num的范围是
1<=num<=3999
所以只需要处理到1000就可以,使用s进行辅助计算,从千位开始逐个获取当前位置的数值t,然后将num降一个数量级——
n
u
m
/
=
s
num /= s
num/=s。因为特殊情况只有4,9,40,90,400,900
,还有5,50,500
,所以对这几个情况进行特殊处理(详细见代码细节),最后可以得到最终结果。
代码
class Solution {
public String intToRoman(int num)
{
// 1 5 10 50 100 500 1000
String[] roman = new String[]{"I","V","X","L","C","D","M"};
// 4 9 40 90 400 900
String[] roman2 = new String[]{"IV","IX","XL","XC","CD","CM"};
String res = "";
int s = 1000;
while(num != 0)
{
int t = num / s;
if (t==4)
{
switch (s){
case 100:res += roman2[4];break;
case 10:res +=roman2[2];break;
case 1:res += roman2[0];break;
}
}
else if (t==9)
{
switch (s){
case 100:res += roman2[5];break;
case 10:res +=roman2[3];break;
case 1:res += roman2[1];break;
}
}
else
while (t>0)
{
if (t>=5){
switch (s){
case 100:res += roman[5];break;
case 10:res +=roman[3];break;
case 1:res += roman[1];break;
}
t-=5;
}
else {
switch (s){
case 1000:res += roman[6];break;
case 100:res += roman[4];break;
case 10:res +=roman[2];break;
case 1:res += roman[0];break;
}
t--;
}
}
num = num % s;
s /= 10;
}
return res;
}
}
思路2模拟
和我做的思路一样,只不过更加简洁,把特殊情况全写入数组内,出现对应的情况就添加对应的罗马字符到最终结果内,更加省时省空间。
代码
public String intToRoman(int num)
{
StringBuffer sb = new StringBuffer();
int[] value = new int[]{ 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
String[] roman = new String[]{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
for(int i=0;i<value.length;i++)
{
int val = value[i];
String rom = roman[i];
while (num>=val)
{
sb.append(rom);
num -= val;
}
}
return sb.toString();
}