• LeetCode(12):整数转罗马数字


    Medium!

    题目描述:

    罗马数字包含以下七种字符: I, V, X, LCD 和 M

    字符          数值
    I             1
    V             5
    X             10
    L             50
    C             100
    D             500
    M             1000

    例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做  XXVII, 即为 XX + V + II 。

    通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

    • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
    • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。 
    • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

    给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

    示例 1:

    输入: 3
    输出: "III"

    示例 2:

    输入: 4
    输出: "IV"

    示例 3:

    输入: 9
    输出: "IX"

    示例 4:

    输入: 58
    输出: "LVIII"
    解释: C = 100, L = 50, XXX = 30, III = 3.
    

    示例 5:

    输入: 1994
    输出: "MCMXCIV"
    解释: M = 1000, CM = 900, XC = 90, IV = 4.(C可以放在D(500)和M(1000)的左边,来表示400和900)

    解题思路:

    例如整数 1437 的罗马数字为 MCDXXXVII, 我们不难发现,千位,百位,十位和个位上的数分别用罗马数字表示了。 1000 - M, 400 - CD, 30 - XXX, 7 - VII。所以我们要做的就是用取商法分别提取各个位上的数字,然后分别表示出来:

    100 - C

    200 - CC

    300 - CCC

    400 - CD

    500 - D

    600 - DC

    700 - DCC

    800 - DCCC

    900 - CM

    我们可以分为四类,100到300一类,400一类,500到800一类,900最后一类。每一位上的情况都是类似的,代码如下:

    C++参考答案一:

     1 class Solution {
     2 public:
     3     string intToRoman(int num) {
     4         string res = "";
     5         char roman[] = {'M', 'D', 'C', 'L', 'X', 'V', 'I'};
     6         int value[] = {1000, 500, 100, 50, 10, 5, 1};
     7         
     8         for (int n = 0; n < 7; n += 2) {
     9             int x = num / value[n];
    10             if (x < 4) {
    11                 for (int i = 1; i <= x; ++i) res += roman[n];
    12             } else if (x == 4) res = res + roman[n] + roman[n - 1];
    13             else if (x > 4 && x < 9) {
    14                 res += roman[n - 1];
    15                 for (int i = 6; i <= x; ++i) res += roman[n];
    16             }
    17             else if (x == 9) res = res + roman[n] + roman[n - 2];
    18             num %= value[n];            
    19         }
    20         return res;
    21     }
    22 };

    本题由于限制了输入数字范围这一特殊性,故而还有一种利用贪婪算法的解法,建立一个数表,每次通过查表找出当前最大的数,减去再继续查表。参见代码如下:

    C++参考答案二:

     1 class Solution {
     2 public:
     3     string intToRoman(int num) {
     4         string res = "";
     5         vector<int> val{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
     6         vector<string> str{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
     7         for (int i = 0; i < val.size(); ++i) {
     8             while (num >= val[i]) {
     9                 num -= val[i];
    10                 res += str[i];
    11             }
    12         }
    13         return res;
    14     }
    15 };

    下面这种方法个人感觉属于比较投机取巧的方法,把所有的情况都列了出来,然后直接按位查表,O(1)的时间复杂度啊,参见代码如下:

    C++参考答案三:

     1 class Solution {
     2 public:
     3     string intToRoman(int num) {
     4         string res = "";
     5         vector<string> v1{"", "M", "MM", "MMM"};
     6         vector<string> v2{"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"};
     7         vector<string> v3{"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"};
     8         vector<string> v4{"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};
     9         return v1[num / 1000] + v2[(num % 1000) / 100] + v3[(num % 100) / 10] + v4[num % 10];
    10     }
    11 };
  • 相关阅读:
    [转].net mvc + vuejs 的项目结构
    Outlook IMAP 修改PST文件存储路径
    VS2017 性能优化方法
    查询存储过程所需参数
    如何保障微服务架构下的数据一致性
    sqlserver批量给用户配置存储过程权限
    vue中刷新当前页面或重新加载的两种方法
    vue history模式下的微信支付,及微信支付授权目录的填写,处理URL未注册
    Vue 四行代码实现无感知上拉加载更多
    2019年前端必用正则(js)
  • 原文地址:https://www.cnblogs.com/ariel-dreamland/p/9128028.html
Copyright © 2020-2023  润新知