LeetCode第13题是将罗马数字转换成阿拉伯数字,也就是我们常用的十进制。(LeetCode第12题是将数字转换成罗马数字,此题相反)
首先,罗马数字用字符串表示,阿拉伯数字用整型表示。先分析给出的几个示例:
1.第一个给出的字符串是罗马数"III”,通过以下对应表,我们遍历累加就可以得出结果是3,简单
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
2.第2个给出的字符串是“IV”,第一个代表1,第2个代表5,“IV”代表(5-1=)4,“VI”表示(5+1=)6。所以像4,9,40,90这种,我们不能直接累加,必须判断前后大小关系再累加
3.第3个字符串是"IX",和第2个类似,X表示10,所以“IX”表示9。
4.直接累加50+5+1+1+1 = 58
5,再看最后一个字符串“MCMXCIV”,M代表1000,C代表100,后面第3个字母M代表1000,这里就应该C和M连起来代表900,然后第4个字母X,X是代表10呢,还是让第5个字母相减呢,
所以还得继续看第5个字母C,C代表100,比X的10大,所以这里CM代表90,剩下最后两个字母“IV”代表4。所以结果就是1000(M)+900(CM)+90(XC)+4(IV) = 1994。
这个时候我们可以有个思路,从第1个字符串开始遍历,我们比较 当前字符串转换成的数字 和 后一个字符串转换成的数字的大小,如果当前数字更大,直接累加,如果后一个数字比当前数字更大,
后一个数字减去当前数字再累加,并将遍历的下标索引跳一格(多加1)。
这个时候会有个问题,如果是“IVI”,第1个字母和第2个字母比较以后,剩下第3个字母,没有下一个字母,怎么办?
所以,在遍历的时候,去除了最后一个索引,如果刚好类似“IVIV”这种,遍历后索引的值刚好等于字符串长度,如果类似“IVI”这样,遍历后索引的值比字符串的长度小1。
因为Jdk1.7之后,switch语句支持字符串,而且这里要多次字符串查找转换成数字,所以单独一个方法查找字符对应的数字。
以下是详细代码:
代码1:
1 public class Test1 { 2 3 public static void main(String[] args) { 4 System.out.println(romanToInt("III")); 5 System.out.println(romanToInt("IV")); 6 System.out.println(romanToInt("IX")); 7 System.out.println(romanToInt("LVIII")); 8 System.out.println(romanToInt("MCMXCIV")); 9 System.out.println(romanToInt("")); 10 System.out.println(romanToInt(null)); 11 System.out.println(romanToInt("C")); 12 } 13 14 public static int romanToInt(String s) { 15 if (s == null) { 16 return 0; 17 } 18 int sum = 0, i = 0, len = s.length(); 19 int current = 0, next = 0; 20 for (; i < len - 1; i++) { 21 current = findNumber(s.charAt(i) + ""); 22 next = findNumber(s.charAt(i + 1) + ""); 23 if (current >= next) { //如果当前罗马字母转成的数字比后一个字母转成的数字大,直接加到结果里面 24 sum += current; 25 } else { 26 sum += next - current; //否则将后一个数字减去当前数字,再加到结果里 27 i++; //并将i的值多加1位 28 } 29 } 30 if (i < len) { //如果i小于字符串的长度,说明还有最后一个字符串没有转化成数字 31 sum += findNumber(s.charAt(len- 1) + ""); 32 } 33 34 return sum; 35 } 36 //查找罗马字符对应的数字 37 private static int findNumber(String str) { 38 int number = 0; 39 switch(str) { 40 case "I": 41 number = 1; 42 break; 43 case "V": 44 number = 5; 45 break; 46 case "X": 47 number = 10; 48 break; 49 case "L": 50 number = 50; 51 break; 52 case "C": 53 number = 100; 54 break; 55 case "D": 56 number = 500; 57 break; 58 case "M": 59 number = 1000; 60 break; 61 default: 62 break; 63 } 64 return number; 65 } 66 67 }
运行时间:
后面我想了一下,我们可以有另一种思路,先把罗马数字代表的数字先相加,然后判断相邻的大小关系,
从索引1开始,判断当前字符转换后的数字和前一个字符转换后的数字的大小关系。如果前一个数字更小,则双倍减去前一个数字。
(比如原本“IV”代表4,直接累加后变成6,6 - 1 *2 = 4,必须减去那个数字的两倍),这样能一直遍历到最后一个字符。
注意这里是遍历了两次,先累加,然后再判断大小关系又遍历了一次。
代码2:
1 public class Test2 { 2 3 public static void main(String[] args) { 4 System.out.println(romanToInt("III")); 5 System.out.println(romanToInt("IV")); 6 System.out.println(romanToInt("IX")); 7 System.out.println(romanToInt("LVIII")); 8 System.out.println(romanToInt("MCMXCIV")); 9 System.out.println(romanToInt("")); 10 System.out.println(romanToInt(null)); 11 System.out.println(romanToInt("C")); 12 } 13 14 public static int romanToInt(String s) { 15 if (s == null || s.length() < 1) { 16 return 0; 17 } 18 int sum = 0, len = s.length(); 19 int current = 0, previous = 0; 20 for (int i = 0; i < len; i++) { 21 current = findNumber(s.charAt(i) + ""); 22 sum += current; 23 } 24 for (int i = 1; i < len; i++) { 25 previous = findNumber(s.charAt(i - 1) + ""); 26 current = findNumber(s.charAt(i) + ""); 27 if (previous < current) { 28 sum -= previous * 2; 29 } 30 } 31 32 return sum; 33 } 34 //查找罗马字符对应的数字 35 private static int findNumber(String str) { 36 int number = 0; 37 switch(str) { 38 case "I": 39 number = 1; 40 break; 41 case "V": 42 number = 5; 43 break; 44 case "X": 45 number = 10; 46 break; 47 case "L": 48 number = 50; 49 break; 50 case "C": 51 number = 100; 52 break; 53 case "D": 54 number = 500; 55 break; 56 case "M": 57 number = 1000; 58 break; 59 default: 60 break; 61 } 62 return number; 63 } 64 65 }
运行时间:
后面还有对第2个代码稍微改进:
代码3:
1 public class Test3 { 2 3 public static void main(String[] args) { 4 System.out.println(romanToInt("III")); 5 System.out.println(romanToInt("IV")); 6 System.out.println(romanToInt("IX")); 7 System.out.println(romanToInt("LVIII")); 8 System.out.println(romanToInt("MCMXCIV")); 9 System.out.println(romanToInt("")); 10 System.out.println(romanToInt(null)); 11 System.out.println(romanToInt("C")); 12 } 13 14 public static int romanToInt(String s) { 15 if (s == null || s.length() < 1) { 16 return 0; 17 } 18 int sum = 0, len = s.length(); 19 int current = 0, previous = 0; 20 21 sum += findNumber(s.charAt(0) + ""); 22 for (int i = 1; i < len; i++) { 23 previous = findNumber(s.charAt(i - 1) + ""); 24 current = findNumber(s.charAt(i) + ""); 25 sum += current; 26 if (previous < current) { 27 sum -= previous * 2; 28 } 29 } 30 31 return sum; 32 } 33 //查找罗马字符对应的数字 34 private static int findNumber(String str) { 35 int number = 0; 36 switch(str) { 37 case "I": 38 number = 1; 39 break; 40 case "V": 41 number = 5; 42 break; 43 case "X": 44 number = 10; 45 break; 46 case "L": 47 number = 50; 48 break; 49 case "C": 50 number = 100; 51 break; 52 case "D": 53 number = 500; 54 break; 55 case "M": 56 number = 1000; 57 break; 58 default: 59 break; 60 } 61 return number; 62 } 63 64 }
运行时间: