Roman to Integer问题
title:
1.问题描述
Given a roman numeral, convert it to an integer.Input is guaranteed to be within the range from 1 to 3999.
{"","I","II","III","IV","V","VI","VII","VIII","IX"},
{"","X","XX","XXX","XL","L","LX","LXX","LXXX","XC"},
{"","C","CC","CCC","CD","D","DC","DCC","DCCC","CM"},
{"","M","MM","MMM"}
题目翻译:
给定一个罗马数字,把这个罗马数字转换成整数,输入的数据范围1-3999
2.解题思路
这道题刚好和整数转罗马数字相反,那么就就可以利用相反的方法,把罗马数字所有的可能出现的情况建立一个数组,然后对各种情况进行判断,就能完成转换。在实现的时候,暴露出对java语言使用不熟悉的问题:
1.char和String的比较
2.substring()的范围问题
在实现这道题的时候边界情况也调整了好久,所以在下手写代码之前,一定要把所有的情况考虑清楚,不然调bug也很懵逼,为什么会出错也要想明白。
刚做这道题的时候,思路是一位一位的读取罗马字母,然后对特殊情况进行判断,如XC、CM,但是实现的时候对于特殊情况处理不好就放弃了,在上面的代码通过之后,我就看了排名第一的代码,也是这种思路,但是大神处理的很好,现在在代码中进行注释来说明。
3.代码实现
1.列举所有可能情况,进行解析
class Solution {
public int romanToInt(String s) {
int len = s.length();
int res = 0;
if(len==0||s==null)
res = 0;
int j=0;
String[] arr= {"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};
//数组保存所有情况
int [] num = {1000,900,500,400,100,90,50,40,10,9,5,4,1};
for(int i =0;i<len;) {
//循环用于处理重复出现的字符
while(i+1<=len&&arr[j].equals(s.substring(i,i+1))) {
res+=num[j];
i++;
}
//判断避免越界
if(i+2<=len) {
//判断包含两个字符的情况
if(arr[j].equals(s.substring(i, i+2)) ) {
res+=num[j];
j++;
i = i+2;
continue;
}
}
//防止越界,同时跳过不匹配的情况
if(i+1<=len && !arr[j].equals(s.substring(i,i+1))) {
j++;
continue;
}
}
return res;
}
}
2.逐位解析,处理特殊情况
class Solution {
public int romanToInt(String s) {
int[] chs = new int[s.length()];
int result = 0;
//把多有字符代表的数值列举出来,一位一位的对应,
//但是这里存在类似CD和DC逆序的问题
for (int i = 0; i < chs.length; i++) {
switch (s.charAt(i)) {
case 'I':
chs[i] = 1; break;
case 'V':
chs[i] = 5; break;
case 'X':
chs[i] = 10; break;
case 'L':
chs[i] = 50; break;
case 'C':
chs[i] = 100; break;
case 'D':
chs[i] = 500; break;
case 'M':
chs[i] = 1000; break;
}
}
for (int i = 0; i < chs.length; i++){
if ( i == chs.length - 1){
result += chs[i];
}
else if (chs[i] < chs [i + 1]){
//处理顺序不同的情况
result = result - chs [i] ;
} else
result += chs[i];
}
return result;
}
}