12.整数转罗马数字

  • 题目描述
    罗马数字包含以下七种字符: I, V, X, L,C,D 和 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"
      解释: L = 50, V = 5, III = 3.
    

示例 5:

	输入: 1994
	输出: "MCMXCIV"
	解释: M = 1000, CM = 900, XC = 90, IV = 4.

如果一开始看这道题时,没有一点思路,那么就用最直接的方法,我们将给定的数字,一步步分解,大于等于1000时是什么情况,大于等于100时是什么情况,大于等于10时是什么情况,大于等于0时是什么情况。虽然可能要分很多种情况,当我们可以看看能不能进行优化。

public static String intToRoman1(int num) {
    String str = "";
    //分解大于等于1000的部分
    if(num>=1000){
        int count = num / 1000;
        for(int i = 0; i < count;i++)
            str += "M";
        num -= count*1000;
    }
     //分解大于等于100的部分
    if(num>=100){
        int count = num / 100;
        if(count==9)
            str+="CM";
        else if(count > 5){
            str += "D";
            int temp = count;
            while(temp > 5){
                str += "C";
                temp--;
            }
        }
        else if(count == 5){
            str += "D";
        }
        else if(count ==4) {
            str += "CD";
        }
        else{
            int temp = count;
            while(temp >= 1){
                str+= "C";
                temp--;
            }
        }
        num -= count*100;
    }
     //分解大于等于10的部分
    if(num>=10){
        int count = num / 10;
        if(count==9){
            str+="XC";
        }
        else if(count > 5){
            str += "L";
            int temp = count;
            while(temp > 5){
                str += "X";
                temp--;
            }
        }
        else if(count == 5){
            str += "L";
        }
        else if(count ==4) {
            str += "XL";
        }
        else{
            int temp = count;
            while(temp >= 1){
                str+= "X";
                temp--;
            }
        }
        num -= count*10;
    }
     //分解大于0的部分
    if(num>0){
        int count = num ;
            if(count==9) {
                str += "IX";
            }
        else if(count > 5){
            str += "V";
            int temp = count;
            while(temp > 5){
                str += "I";
                temp--;
            }
        }
        else if(count == 5){
            str += "V";
        }
        else if(count ==4) {
            str += "IV";
        }
        else {
                int temp = count;
                while(temp >= 1){
                    str+= "I";
                    temp--;
                }
        }
    }

    return str;
}

观察上面的代码,我们可以明显看出,每个分解的部分,基本都一样,那么我们可以优化这些相同的部分。同时上面这段代码的可拓展性极差,如果出现10000的数字,那么将有新的罗马数字,同时需要再上面的代码中写出大量篇幅的代码。

接下来是优化代码,我们需要建立数字与罗马字符的映射关系,所以需要集合。代码如下:

public static String intToRoman(int num){
    Map<Integer,String> map = new HashMap<Integer, String>();
    map.put(1,"I");
    map.put(5,"V");
    map.put(10,"X");
    map.put(50,"L");
    map.put(100,"C");
    map.put(500,"D");
    map.put(1000,"M");

    String str = "";
    int count = 0;
    int m = 1000;
    while (num > 0){
        count = num / m;
        num -= count * m;

        if(count==9){
            str += map.get(m)+map.get(m*10);
        }

        else if(count >= 5){
            str += map.get(5 * m);
            while(count-- > 5){
                str += map.get(m);
            }
        }
        else if(count == 4){
            str += map.get(m)+map.get(5 * m);
        }
        else{
            while(count-- > 0)
                str += map.get(m);
        }
        m /= 10;
    }

    return str;
}

这段代码是不是比第一段代码简洁了许多?通过总结第一段代码可以很容易得到上面的代码。而且这段代码的拓展形较高,到出现更大的数字时,只需要将映射关系加入集合,同时更改m的初值即可。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值