一、问题描述
Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.
roman numerals:http://literacy.kent.edu/Minigrants/Cinci/romanchart.htm
二、我的思路
想到了用前后数字的关系决定是加还是减,但是卡住了…因为对右减的理解不够深刻。
右边要减掉的数字最多连续一位,没有连续的多位。而且要减掉的只有I,X,C这种最高位为1的字母。
计数规则参考:http://blog.csdn.net/wzy_1988/article/details/17057929
三、淫奇技巧
1. 常规法:从左向右处理,如果高位比低位数字小,说明要减去,否则做加法。
另辟一个数组,把每一位char转换成int再处理。我是用了Map存储转换规则,每次查表。他这样的做法省时间。
public int romanToInt(String s) {
int nums[]=new int[s.length()];
for(int i=0;i<s.length();i++){
switch (s.charAt(i)){
case 'M':
nums[i]=1000;
break;
case 'D':
nums[i]=500;
break;
case 'C':
nums[i]=100;
break;
case 'L':
nums[i]=50;
break;
case 'X' :
nums[i]=10;
break;
case 'V':
nums[i]=5;
break;
case 'I':
nums[i]=1;
break;
}
}
int sum=0;
for(int i=0;i<nums.length-1;i++){
if(nums[i]<nums[i+1])
sum-=nums[i];
else
sum+=nums[i];
}
return sum+nums[nums.length-1];
}
2. 有点淫奇~
先把前面数字比后面数字小的情况减去相应的数字。再把各位字母按照转换规则加起来。
比如IV,如果直接加和的话是1+5=6,但是因为罗马计数左减右加的规则,实际为5-1=4.这样就差了2,所以减去2.
public int romanToInt(String s) {
int sum=0;
if(s.indexOf("IV")!=-1){sum-=2;}
if(s.indexOf("IX")!=-1){sum-=2;}
if(s.indexOf("XL")!=-1){sum-=20;}
if(s.indexOf("XC")!=-1){sum-=20;}
if(s.indexOf("CD")!=-1){sum-=200;}
if(s.indexOf("CM")!=-1){sum-=200;}
char c[]=s.toCharArray();
int count=0;
for(;count<=s.length()-1;count++){
if(c[count]=='M') sum+=1000;
if(c[count]=='D') sum+=500;
if(c[count]=='C') sum+=100;
if(c[count]=='L') sum+=50;
if(c[count]=='X') sum+=10;
if(c[count]=='V') sum+=5;
if(c[count]=='I') sum+=1;
}
return sum;
}
从低位开始处理字符串,把处理过的低位和算出来。根据低位和和当前位的关系,判断是加是减。
因为左加右减规则中,减去的数字只有1,10,100这种最高位是1的,所以遇到5x这种直接加,遇到1x这种判断一下再决定加减。
要减去的左边数字比右边的数字和小,而且最多只减去一位。I如果出现在尾部>=5的地方,则减去,否则加上,以此类推……
public static int romanToInt(String s) {
int res = 0;
for (int i = s.length() - 1; i >= 0; i--) {
char c = s.charAt(i);
switch (c) {
case 'I':
res += (res >= 5 ? -1 : 1);
break;
case 'V':
res += 5;
break;
case 'X':
res += 10 * (res >= 50 ? -1 : 1);
break;
case 'L':
res += 50;
break;
case 'C':
res += 100 * (res >= 500 ? -1 : 1);
break;
case 'D':
res += 500;
break;
case 'M':
res += 1000;
break;
}
}
return res;
}
四、知识点
String s的处理:
变成数组 -- char[] c = s.toCharArray();
取第i位 -- s.charAt(i);
switch() case用法。
五、碎碎念
似乎每个优秀答案里面都有自己想法的影子,从影子到清晰的思路差距还是很大啊~
继续加油~~