LeetCode刷题日志-Roman To Integer

Posted by ijays on August 2, 2018

昨晚刷题,随机选到了一道把罗马数字转换为整型的问题。

题目

在罗马数字中使用以下字符来表示特定的数字,

Symbols Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

罗马数字一般从左到右书写,表示数值为各值相加,如VI表示5+1=6。但是如果I在V的左边表示5-1=4,同理,

  • I 在 V 或者 X 左边表示为4和9
  • X 在 L 或者 C 左边表示为90和100
  • C在 D 或者 M 左边表示为900和1000

最后题目还有个提示,数字在1和3999之间。

思路

其实看到这道题的时候开始觉得很简单,用一个哈希表存储罗马字符与整数的映射,然后将传入的字符串转成单个字符读取对应的数字,再判断数字是否是需要减去前面的数字。

写了一会儿代码,前面都很顺利,直到写到如何判断前面的数字需要减去,在这里卡了一会儿。经过仔细观察数字的规律得知,想 IX 这种需要减去前面的数字的罗马数都是能被 5 整除的。如果我们写一个 for 循环,去读取当前字符对应的数字,并且读取下一个字符对应的数字,如果下一个数字能够满族被5整除的条件,那么就将当前数字置为负数,最后将所有的数字加起来得到结果。

我的答案

class Solution {
    public int romanToInt(String s) {
        if(s == null || s.length == 0){
            return 0;
        }
        Map<String, String> map = new HashMap<>(8);
        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[] array = s.toCharArray();
        int count = 0;
        for (int i = 0; i < array.length; i++) {
            int value = Integer.parseInt(map.get(String.valueOf(array[i])));
            if (i + 1 < array.length) {
                //读取下一个字符对应的值
                int valueNext = Integer.parseInt(map.get(String.valueOf(array[i + 1])));
                if ((valueNext % 5 == 0 && value % 5 != 0) || ((valueNext % 500 == 0) && value % 500 != 0) || ((valueNext % 50 == 0) && value % 50 != 0)) {
                 //如果下一个数字满足条件,就将当前数值置为负数
                    value = 0 - value;
                }

            }
            count = value + count;

        }
        return count;
    }
}

反思

做完后回过头来想,这里从前往后扫,判断的是下一个值是否满足条件。其实也可以判断当前值是否比上一个值大,如IV,做法类似,但是判断逻辑中会少很多模运算,这也是网上很多人的做法。