leetcode算法题 pro12 整数转罗马数字

leetcode算法题 pro12 整数转罗马数字

原题地址:https://leetcode-cn.com/problems/integer-to-roman/

题目内容

罗马数字包含以下七种字符: 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。
给你一个整数,将其转为罗马数字。

 

题目分析

第一眼看到这题目想到的是暴力的解法,将每一位的数字逐个取出,转换成相对应的罗马字符,然后再拼接起来。更高级的做法是使用贪心的思想,这题中出现的罗马数字情况无非以下几种,"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I",分别对应1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1,

根据罗马数字的唯一表示法,为了表示一个给定的整数 num,我们寻找不超过num 的最大符号值,将num 减去该符号值,然后继续寻找不超过 num 的最大符号值,将该符号拼接在上一个找到的符号之后,循环直至 num 为 0。最后得到的字符串即为 num 的罗马数字表示。

编程时,可以建立一个数值-符号对的列表valueSymbols,按数值从大到小排列。遍历 valueSymbols 中的每个数值-符号对,若当前数值value 不超过 ,则从 中不断减去value,直至num 小于value,然后遍历下一个数值-符号对。若遍历中num 为 0则跳出循环。

这个解法使用了贪心算法,尽可能优先使用较大数值对应的字符,最后转换得到的罗马数字的字符个数更少,字符更少更方便交流使用,这应该是设计罗马数字的人们的初衷。

 

代码

1.暴力解法

 1  public String intToRoman(int num) {
 2         int q = num / 1000;//取出千位
 3         num = num % 1000;
 4         int b = num / 100;//取出百位
 5         num = num % 100;
 6         int s = num / 10;//取出十位
 7         int g = num % 10;//取出个位
 8         String result = "";
 9         for (int i = 1; i <= q; i++) {
10             result += "M";
11         }
12         if (b < 4) {
13             for (int i = 1; i <= b; i++) {
14                 result += "C";
15             }
16         } else if (b == 4) {
17             result += "CD";
18         } else if (b == 5) {
19             result += "D";
20         } else if (b == 9) {
21             result += "CM";
22         } else {
23             result += "D";
24             for (int i = 6; i <= b; i++) {
25                 result += "C";
26             }
27         }
28 
29         if (s < 4) {
30             for (int i = 1; i <= s; i++) {
31                 result += "X";
32             }
33         } else if (s == 4) {
34             result += "XL";
35         } else if (s == 5) {
36             result += "L";
37         } else if (s == 9) {
38             result += "XC";
39         } else {
40             result += "L";
41             for (int i = 6; i <= s; i++) {
42                 result += "X";
43             }
44         }
45 
46         if (g < 4) {
47             for (int i = 1; i <= g; i++) {
48                 result += "I";
49             }
50         } else if (g == 4) {
51             result += "IV";
52         } else if (g == 5) {
53             result += "V";
54         } else if (g == 9) {
55             result += "IX";
56         } else {
57             result += "V";
58             for (int i = 6; i <= g; i++) {
59                 result += "I";
60             }
61         }
62         //System.out.println(q + "," + b + "," + s + "," + g + ",");
63         return result;
64     }

2.使用贪心算法

public class Solution {

    public String intToRoman(int num) {
        // 把阿拉伯数字与罗马数字可能出现的所有情况和对应关系,放在两个数组中,并且按照阿拉伯数字的大小降序排列
        int[] nums = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
        String[] romans = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};

        StringBuilder stringBuilder = new StringBuilder();
        int index = 0;
        while (index < 13) {
            // 特别注意:这里是等号
            while (num >= nums[index]) {
                stringBuilder.append(romans[index]);
                num -= nums[index];
            }
            index++;
        }
        return stringBuilder.toString();
    }
}

 

官方题解网址:https://leetcode-cn.com/problems/integer-to-roman/solution/zheng-shu-zhuan-luo-ma-shu-zi-by-leetcod-75rs/

posted @ 2021-05-14 15:15  TidalCoast  阅读(35)  评论(0编辑  收藏  举报