LeetCode 面试经典150题 [18/150 整数转罗马数字]


avatar
GuoYulong 2024-06-20 213

题目描述

七个不同的符号代表罗马数字,其值如下:

符号
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:

  • 如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
  • 如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)。
  • 只有 10 的次方(I, X, C, M)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式

给定一个整数,将其转换为罗马数字。

示例 1:

输入:num = 3749

输出: "MMMDCCXLIX"

解释:

3000 = MMM 由于 1000 (M) + 1000 (M) + 1000 (M)
 700 = DCC 由于 500 (D) + 100 (C) + 100 (C)
  40 = XL 由于 50 (L) 减 10 (X)
   9 = IX 由于 10 (X) 减 1 (I)
注意:49 不是 50 (L) 减 1 (I) 因为转换是基于小数位

示例 2:

输入:num = 58

输出:"LVIII"

解释:

50 = L
 8 = VIII

示例 3:

输入:num = 1994

输出:"MCMXCIV"

解释:

1000 = M
 900 = CM
  90 = XC
   4 = IV

个人C++解答

用贪心就可以出来

class Solution {
public:
    string intToRoman(int num) {
        vector<int> value={1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
        vector<string> key = { "M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I" };

        string str = "";
        for (int i=0; i<value.size();i++) {
            while(num >= value[i]) {
                str.append(key[i]);
                num -= value[i];
            }
        }
        return str;
    }
};

其他解答

这道题并不难,其实按照罗马数字转整数的思路做就可以,有趣的是,这道题的评论区佬们的做法,请大家欣赏:

官方解答2:硬编码数字

fig3

回顾前言中列出的这 131313 个符号,可以发现:

千位数字只能由 M 表示;
百位数字只能由 C,CD,D 和 CM 表示;
十位数字只能由 X,XL,L 和 XC 表示;
个位数字只能由 I,IV,V 和 IX 表示。
这恰好把这 13 个符号分为四组,且组与组之间没有公共的符号。因此,整数 num 的十进制表示中的每一个数字都是可以单独处理的。

进一步地,我们可以计算出每个数字在每个位上的表示形式,整理成一张硬编码表。如下图所示,其中 0 对应的是空字符串。

fig4

利用模运算和除法运算,我们可以得到 num 每个位上的数字:

thousands_digit = num / 1000 
hundreds_digit = (num % 1000) / 100 
tens_digit = (num % 100) / 10 
ones_digit = num % 10 

最后,根据 num 每个位上的数字,在硬编码表中查找对应的罗马字符,并将结果拼接在一起,即为 num 对应的罗马数字

const string thousands[] = {"", "M", "MM", "MMM"};
const string hundreds[]  = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
const string tens[]      = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
const string ones[]      = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};

class Solution {
public:
    string intToRoman(int num) {
        return thousands[num / 1000] + hundreds[num % 1000 / 100] + tens[num % 100 / 10] + ones[num % 10];
    }
};

ID:“抓蚂蚁的小高手” 题解

class Solution {
    public:
     string intToRoman(int num) {
        string rome = "IIIVIIIXXXLXXXCCCDCCCMMM";
        string ret = "";
        int p = 0;
        while (num > 0) {
            int q = num % 10;
            if (q < 4)
                ret = rome.substr(p, q) + ret;
            else if (q == 4)
                ret = rome.substr(p + q - 2, 2) + ret;
            else if (q < 9)
                ret = rome.substr(p + 3, q - 4) + ret;
            else
                ret = rome.substr(p + 6, 2) + ret;
            num /= 10;
            p += 7;
        }
        return ret;
    }
};

ID:“imp” 题解

“ipm”:“最无脑的程序,没有之一,不接受反驳(源程序太长,截取部分)”

public String intToRoman(int num) {
        String[] arr = new String[]{"","I","II","III","IV","V","VI","VII","VIII","IX","X","XI","XII","XIII","XIV","XV","XVI","XVII","XVIII","XIX","XX","XXI","XXII","XXIII","XXIV","XXV","XXVI","XXVII","XXVIII","XXIX","XXX","XXXI","XXXII","XXXIII","XXXIV","XXXV","XXXVI","XXXVII","XXXVIII","XXXIX","XL","XLI","XLII","XLIII","XLIV","XLV","XLVI","XLVII","XLVIII","XLIX","L","LI","LII","LIII","LIV","LV","LVI","LVII","LVIII","LIX","LX","LXI","LXII","LXIII","LXIV","LXV","LXVI","LXVII","LXVIII","LXIX","LXX","LXXI","LXXII","LXXIII","LXXIV","LXXV","LXXVI","LXXVII","LXXVIII","LXXIX","LXXX","LXXXI","LXXXII","LXXXIII","LXXXIV","LXXXV","LXXXVI","LXXXVII","LXXXVIII","LXXXIX","XC","XCI","XCII","XCIII","XCIV","XCV","XCVI","XCVII","XCVIII","XCIX","C","CI","CII","CIII","CIV","CV","CVI","CVII","CVIII","CIX","CX","CXI","CXII","CXIII","CXIV","CXV","CXVI","CXVII","CXVIII","CXIX","CXX","CXXI","CXXII","CXXIII","CXXIV","CXXV","CXXVI","CXXVII","CXXVIII","CXXIX","CXXX","CXXXI","CXXXII","CXXXIII","CXXXIV","CXXXV","CXXXVI"
        };
        return arr[num];
    }

ID:“Yimi” 题解

“Yimi”:“啊我写的好长,思路跟官方的 方法二:硬编码数字 一致”

class Solution {
public:
    string intToRoman(int num) {
        string ans = "";
        int M = num / 1000;
        num %= 1000;
        int C = num / 100;
        num %= 100;
        int X = num / 10;
        num %= 10;
        int I = num;
        num %= 1;
        switch (M) {
        case 3:
            ans += 'M';
        case 2:
            ans += 'M';
        case 1:
            ans += 'M';
        case 0:
            break;
        }
        switch (C) {
        case 9:
            ans += "CM";
            break;
        case 8:
            ans += "DCCC";
            break;
        case 7:
            ans += "DCC";
            break;
        case 6:
            ans += "DC";
            break;
        case 5: 
            ans += "D";
            break;
        case 4:
            ans += "CD";
            break;
        case 3:
            ans += 'C';
        case 2:
            ans += 'C';
        case 1:
            ans += 'C';
        case 0:
            break;
        }
        switch(X) {
        case 9:
            ans += "XC";
            break;
        case 8:
            ans += "LXXX";
            break;
        case 7:
            ans += "LXX";
            break;
        case 6:
            ans += "LX";
            break;
        case 5: 
            ans += "L";
            break;
        case 4:
            ans += "XL";
            break;
        case 3:
            ans += 'X';
        case 2:
            ans += 'X';
        case 1:
            ans += 'X';
        case 0:
            break;
        }
        switch(I) {
        case 9:
            ans += "IX";
            break;
        case 8:
            ans += "VIII";
            break;
        case 7:
            ans += "VII";
            break;
        case 6:
            ans += "VI";
            break;
        case 5: 
            ans += "V";
            break;
        case 4:
            ans += "IV";
            break;
        case 3:
            ans += 'I';
        case 2:
            ans += 'I';
        case 1:
            ans += 'I';
        case 0:
            break;
        }
        return ans;
    }
};

ID:"Happy Grothendieckcvx"题解

"Happy Grothendieckcvx":用不了一点枚举 没有四千限制也能打

string intToRoman(int num) {
    map<int,char> roma;
    roma.insert(pair<int,char>(6,'M'));
    roma.insert(pair<int,char>(5,'D'));
    roma.insert(pair<int,char>(4,'C'));
    roma.insert(pair<int,char>(3,'L'));
    roma.insert(pair<int,char>(2,'X'));
    roma.insert(pair<int,char>(1,'V'));
    roma.insert(pair<int,char>(0,'I'));

    string sorted;

    for(int i=4;i>0;i--){
        int temp=num%(int)pow(10,i)/(int)pow(10,i-1);
        if(temp==9){
            sorted+=roma[i*2-2];
            sorted+=roma[i*2];
            continue;
        }
        if(temp==4){
            sorted+=roma[i*2-2];
            sorted+=roma[i*2-1];
            continue;
        }
        if(temp>=5){
            sorted+=roma[i*2-1];
            temp-=5;              
        }
        for(int j=0;j<temp;j++){
            sorted+=roma[i*2-2];
        }
    }
    return sorted;
}

相关阅读

注意!!!

站点域名更新!!!部分文章图片等由于域名问题无法显示!!!

通知!!!

站点域名更新!!!部分文章图片等由于域名问题无法显示!!!