罗马数字转整型

一. 题目描述

罗马数字包含以下七种字符:I, V, X, LCD 和 M

字符          数值
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

二. 我的解法

2.1 代码

class Solution {
    public int romanToInt(String s) {
        HashMap<String, Integer> numbers = new HashMap<>();
        numbers.put("I",1);
        numbers.put("V",5);
        numbers.put("X",10);
        numbers.put("L",50);
        numbers.put("C",100);
        numbers.put("D",500);
        numbers.put("M",1000);

        int result = 0;

        for(int i = 0; i < s.length(); i++){
            String luoma_i = s.substring(i,i+1);

            String luoma_j = "";
            if(i < s.length() - 1)
                luoma_j = s.substring(i+1, i+2);
            else {
                result += numbers.get(luoma_i);
                break;
            }
            //判断是否前面的罗马数字比后面的罗马数字小
            int number_i = numbers.get(luoma_i);
            int number_j = numbers.get(luoma_j);

            if( number_i < number_j ){
                result += number_j - number_i;
                i += 1; // 由于直接处理了两位数字,所以目前已经处理到了下标为i+1的罗马数字
            }else{
                result += number_i;
            }
        }

        return result;
    }
}

2.2 分析

1. 为了能够更快地去获取罗马数字对应的阿拉伯数字,使用hashMap容器进行存储。

2. 遍历整个字符串,并判断当前字符是否为最后一个字符,如果是,则直接将其对应的阿拉伯数字与result求和,并退出循环,如果不是,则获取字符串的下一个字符,用以后续的比较。

3. 由于阿拉伯数字存在IV这种特殊情况,所以在转换时需要单独列出来进行处理,通过获取当前字符以及其下一个字符的数值,并比较两个数值, 如果前一个数值比下一个数值小,则判定为特殊情况,并进行对应的特殊处理,此时,会同时完成两个字符的处理,令 i += 1 来跳过已经处理了的字符。

三. 更优解法

3.1 代码

class Solution {
    public int romanToInt(String s) {
       Map<Character,Integer> map = new HashMap<>();
		map.put('I', 1);
		map.put('V', 5);
		map.put('X', 10);
		map.put('L', 50);
		map.put('C', 100);
		map.put('D', 500);
		map.put('M', 1000);
		char[] chs = s.toCharArray();
		int result = 0;
		for (int i = 0; i < chs.length; i++) {
			if(i == chs.length -1) {
				result += map.get(chs[i]);
				continue;
			}
			if(map.get(chs[i])<map.get(chs[i+1])) {
				result -= map.get(chs[i]);
			}else {
				result += map.get(chs[i]);
			}
		}
		
		return result;
    }
}

3.2 分析

1. 这个代码与我的代码的主要区别就在于他处理特殊情况的方式。

2. 其实我觉得在其 result -= map.get(chs[i]);之后可以加 { result += map.get(chs[i+1]); i += 1; } 这样子的话, 速度会进一步地提升,但是, 代码的可读性也会降低一些(还是无伤大雅吧)。

3. 另外就是,他的程序里, 没有像我那样,为每一个取出来的数重新定义一个变量存放,所以,相对来说要更加整洁,速度方面也会更快一些。值得学习。

四. 参考

https://leetcode-cn.com/problems/roman-to-integer/description/

 

猜你喜欢

转载自blog.csdn.net/qq_28634403/article/details/81213364