算法小知识----11.01----罗马数字转整数

320 阅读2分钟

这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战

罗马数字转整数

该题出自力扣的13题——罗马数字转整数,题解是自己做的

审题

整道题其实就是一个意思:给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

由字符串转成整型数字

  • 常规逻辑的话,正面遍历,可能会比较麻烦难搞

    • 因为罗马数字的特性——IV是4,也就是说小的在左边的情况下需要减
    • 这也是需要判断的点,相对会比较繁琐
  • 如果从后面去遍历的话,情况就会比较清晰

    • 从后往前遍历,如果是更大的或者同级则相加更新
    • 记录当前的罗马数字对应的值,作为下次的比较
    • 如果是小的则相减
  • 时间复杂度是O(n),空间复杂度会较高,虽然是O(1),但还是开辟了额外的空间去存储罗马数字

编码

        Map<Character, Integer> map = new HashMap<Character, Integer>() {{
        put('I', 1);
        put('V', 5);
        put('X', 10);
        put('L', 50);
        put('C', 100);
        put('D', 500);
        put('M', 1000);
    }};
    public int romanToInt(String s) {
​
        //从右边开始遍历,如果是更大的或者同级则相加更新;如果是小的则相减
        int lengtn = s.length();
        int num = 0;
        int index = 0;
        for (int i = lengtn-1;i>=0;i--){
            char c = s.charAt(i);
            if (map.get(c)>= index){
                index = map.get(c);
                num = num + index;
            }else {
                index = map.get(c);
                num = num - index;
            }
        }
        return num;
    }

彩蛋

其实,可以有相对更好的解法,虽然并无伤大雅,但是却可以提高空间复杂度。在上述的解法中,因为要额外开辟空间给HashMap,又因为HashMap在少数据量的情况下,性能并是最好的。

  • 可以使用switch取代Hashmap
public static Integer numChange(Character c){
    switch (c){
        case 'I':
            return 1;
        case 'V':
            return 5;
        case 'X':return 10;
        case 'L':return 50;
        case 'C':return 100;
        case 'D':return 500;
        case 'M':return 1000;
        default:return 0;
    }
}
  • 总体来说是优化了三次
    • 第一次是把HashMap放在里层,等于是每次调用再初始化,也就是类似单例中懒汉的模式
    • 第二次是做了全局,类似单例中的饿汉模式,空间小了了0.2MB
    • 第三次就是调用switch,时间少了一半,空间也少了 1635470568(1).jpg