题目
这道题是要将字符串形式的罗马数字转换为整型。罗马数字由一些基本字母构成,其和阿拉伯数字之间的联系如下:
罗马数字 | 阿拉伯数字 |
---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
还在leetcode上只需要我们输入1-2999之间的罗马数字。
思路
认真研究罗马数字表示,我们可以归纳出以下几个规律,先约定,遍历字符串,从头开始遍历,也就是IIV会先遍历I
1. 当前字符大于前一个字符且小于之前所有字符,如VIV中的后一个V为当前字符
2. 当前字符大于前一个字符且大于之前素有字符,IIV中的V为当前字符
3. 当前字符等于之前字符,如VV中的第二个V字符为当前字符
4. 当前字符小于之前字符 ,如VI
计算规则
这是最难的部分,在不同的情况下,计算规则是不一样的。
根据4个思路,规定计算规则如下:
如果情况4出现,就讲当前值累加上去即可。例如VI,I为当前值,就将1累加到结果上去。
如果情况3出现,如4一样处理
如果情况2出现,将当前值减去之前所有值,就为结果。如IIV,若当前值为V(5),那么结果就为5-2。
最复杂的是情况1。先来看看MCMXCVI这个应该为多少,这个结果是1996。是1000(M)+900(CM)+90(XC)+6(VI)。那么归纳如下:
如果情况1出现,那么结果(retInt)等于累加上当前字符(curNum)但是要减去之前字符(preNum)的两倍。因为,这个应该在总体上减去一次的,但是前面加了一次,所以要减去两次。如,VIV,当curNum为I时候,将I加在结果上的。还是以VIV为例子:
第一次遍历:curNum为V,preNum为初始值0,所以retInt==5
第二次遍历:curNUm为I,preNum为V,根据规则,retInt=retInt+1=6
第三次遍历:curNUm为V,preNum为I,根据规则,retInt=retInt+5-1=10。然而结果应该为9,就是因为正确的应该为retInt=retInt+5-2*1=9。
public class QuickStart {
public int romanToInt(String s) {
int len = s.length();
int retInt = 0;
char curCh;
int curNum = 0;
int preNum = 0;
for(int i = 0;i<len;++i){
curCh = s.charAt(i);
switch (curCh){
case 'I':curNum = 1;break;
case 'V':curNum = 5;break;
case 'X':curNum = 10;break;
case 'L':curNum = 50;break;
case 'C':curNum = 100;break;
case 'D':curNum = 500;break;
case 'M':curNum = 1000;break;
default :curNum = 0;break;
}
if(curNum == preNum ){
retInt += curNum;
}else if(curNum<preNum )
{
retInt += curNum;
}else if(curNum>preNum && curNum<retInt){
retInt += (curNum - 2*preNum );
}else if(curNum>preNum && curNum>=retInt){
retInt = curNum - retInt;
}else{
}
preNum = curNum;
}
return retInt;
}
//main-test
public static void main(String[] args) {
QuickStart quickStart = new QuickStart();
System.out.println(quickStart.romanToInt("MCMXCVI"));
}
}