Bootstrap

从零开始的CPP(26)映射表储存对应关系解决整数——罗马数转换问题

leetcode12

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

符号
I1
V5
X10
L50
C100
D500
M1000

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

  • 如果该值不是以 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 的次方(IXCM)最多可以连续附加 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) 因为转换是基于小数位

最开始用了暴力枚举法

class Solution {
public:
    string intToRoman(int num) {
        string res;
        if (num / 1000 > 0) {
            int a = num / 1000;
            num = num - 1000 * a;
            while (a != 0) {
                res.push_back('M');
                a--;
            }           
        }
        if (num / 100 > 0) {
            int a = num / 100;
            num = num - 100 * a;
            if (a == 4) {
                res.push_back('C');
                res.push_back('D');
            }
            else if (a == 9) {
                res.push_back('C');
                res.push_back('M');
            }
            else if (a < 4){
                while (a != 0) {
                    res.push_back('C');
                    a--;
                }
            }
            else if (a >= 5) {
                res.push_back('D');
                while (a != 5) {
                    res.push_back('C');
                    a--;
                }
            }
        }
        if (num / 10 > 0) {
            
            int a = num / 10;
            //cout << "十分位是:" << a << endl;
            num = num - 10 * a;
            if (a == 4) {
                //cout << res << endl;
                res.push_back('X');
                res.push_back('L');
                //cout << res << endl;
            }
            else if (a == 9) {
                res.push_back('X');
                res.push_back('C');
            }
            else if (a < 4) {
                while (a != 0) {
                    res.push_back('X');
                    a--;
                }
            }
            else if (a >= 5) {
                res.push_back('L');
                while (a != 5) {
                    res.push_back('X');
                    a--;
                }
            }
        }
        if (num / 1 > 0) {
            int a = num / 1;
            //cout << "个位是:" << a << endl;
            num = num - 1 * a;
            if (a == 4) {
                res.push_back('I');
                res.push_back('V');
            }
            else if (a == 9) {
                res.push_back('I');
                res.push_back('X');
            }
            else if (a < 4) {
                while (a != 0) {
                    res.push_back('I');
                    a--;
                }
            }
            else if (a >= 5) {
                res.push_back('V');
                while (a != 5) {
                    res.push_back('I');
                    a--;
                }
            }
        }
        return res;
    }
};

不过这样写太乱了,就用映射表换成了更简洁的写法。因为运行时默认从最小的{1,“I”}开始循环,所以我们从末尾开始遍历,直到开头(注意前移一位迭代器),其他思路一样。

class Solution {
public:
    string intToRoman(int num) {
    string res="";
    map<int, string> romamap{
        {1000,"M"},{900,"CM"},{500,"D"},{400,"CD"},{100,"C"},{90,"XC"},{50,"L"},{40,"XL"},{10,"X"},{9,"IX"},{5,"V"},{4,"IV"},{1,"I"} };
    for (auto it = --romamap.end(); it != --romamap.begin(); it--) {
        //cout << it->first << endl;
        while (num >= it->first) {
            res = res + it->second;
            num = num - it->first;
        }
    }
    return res;
}
};

 当然,这变成了双循环,运行速度变慢了

;