LeetCode 12 整数转罗马数字

159 阅读3分钟

「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。

题目:字面含义,整数转罗马数字,罗马数字共七个,分别为IVXLCDM。其分别对应1510501005001000,除了4和9的一倍、十倍以及百倍为特殊情况,其余数字表示都正常。详细题目看LeetCode 第12题。此处有一个提示,输入的num的取值范围为1~3999。

解题思路

首先看到num的取值范围1~3999,也就是说我们千位只需要关注0-3即可,并且例如数字1994,其对应的输出为"MCMXCIV",拆开即为M + CM + XC + IV,分别对应千位、百位、十位、个位。因此本题的关键点就是将输入的num进行拆分,拆分之后进行简单的判断即可,如果是4和9就进行特殊处理,如果是其他数字则常规拼接。但这样代码可能会出现很多的if else ,代码易读性较差,一种更常规的思路是首先列举出每位所有可能的情况,之后根据各十百千位的不同进行选择即可,之后对选择出的字符进行拼接即为正确结果。

此处列出所有情况选择的数据结构是数组,可以在数组中列举每个位在0~9所有可能的情况,之后根据计算的实际数值,去数组中选择具体的字符,此时就不需要考虑4和9不同位的特殊性了,列举的所有情况如下:

  • 对于千位,只需要考虑前四种。String[] thousands = {"", "M", "MM", "MMM"};

  • 百位以及之下则是所有情况:String[] hundreds = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};

  • 十位:String[] tens = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};

  • 个位: String[] ones = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};

    具体代码如下:

    public static String intToRoman(int num){
            String[] thousands = {"", "M", "MM", "MMM"};
            String[] hundreds = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
            String[] tens = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
            String[] ones = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
            int thousand = num / 1000;
            int hundred = num % 1000 / 100;
            int ten = num % 100 / 10;
            int one = num % 10;
            return thousands[thousand] + hundreds[hundred] + tens[ten] + ones[one];
        }
    

算法的时间复杂度和空间复杂度都是O(1)O(1)。最终运行结果:

image-20220121104505082.png

相似题目:罗马数字转阿拉伯数字

本题的题目可见LeetCode第13题。

解题思路

本题思路很关键的一点是将罗马字符串切分开,之后有一个很重要的性质就是切分开后的字符转阿拉伯数字,如果不是4和9特殊情况的话前一个字符数字必然大于后一个,如果不存在这种性质,则表示出现了特殊情况,此时就需要将结果相减一下,代码如下:

private static int getInt(char c){
        int num = 0;
        switch (c){
            case 'I':
                num = 1;
                break;
            case 'V':
                num = 5;
                break;
            case 'X':
                num = 10;
                break;
            case 'L':
                num = 50;
                break;
            case 'C':
                num = 100;
                break;
            case 'D':
                num = 500;
                break;
            case 'M':
                num = 1000;
                break;
        }
        return num;
    }

    public static int RomanToInt(String s){
        char[] chars = s.toCharArray();
        int RomanNum = 0;
        for(int i=0;i<chars.length-1;i++){
            int prior = getInt(chars[i]);
            int next = getInt(chars[i+1]);
            if(prior<next){
                RomanNum -= prior;
            }else {
                RomanNum += prior;
            }
        }
        return RomanNum + getInt(chars[chars.length-1]);
        }

总结

两题思路其实不难,主要思想就是列举,看清题意,列举出所有情况即可。