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(); } }