这是悦乐书的第351次更新,第376篇原创
java
今天介绍的是LeetCode算法题中Medium级别的第6题(顺位题号是12)。罗马数字由七个不一样的符号表示:I,V,X,L,C,D和M.算法
符号 值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000
例如,2用罗马数字写成II
,由两个I加在一块儿。12写为XII
,简称为X + II
。
27写成XXVII
,即XX + V + II
。数组
罗马数字一般从左到右从最大到最小。可是,四个数字不是IIII
。相反,4写为IV
。
由于I
在V
以前,咱们作减法获得4。一样的原则适用于9,9被写为IX
。有六个使用减法的实例:数据结构
I
能够放在V
(5)和X
(10)以前,获得4和9。
X
能够放在L
(50)和C
(100)以前,获得40和90。
C
能够放在D
(500)和M
(1000)以前,获得400和900。app
给定一个整数,将其转换为罗马数字。输入保证在1到3999的范围内。例如:ui
输入:3
输出:“III”code
输入:4
输出:“IV”字符串
输入:9
输出:“IX”class
输入:58
输出:“LVIII”
说明:L = 50,V = 5,III = 3。基础
输入:1994
输出:“MCMXCIV”
说明:M = 1000,CM = 900,XC = 90,IV = 4。
题目要求咱们将整数转成罗马数字符串来表示,和以前遇到的罗马数字符串转整数正好相反。
题目限定了num的范围,[1,3999]
,针对常见的数字,列了下面这些罗马数和整数的对应关系:
900 CM 90 XC 9 IX 800 DCCC 80 LXXX 8 VIII 700 DCC 70 LXX 7 VII 600 DC 60 LX 6 VI 500 D 50 L 5 V 400 CD 40 XL 4 IV 3000 MMM 300 CCC 30 XXX 3 III 2000 MM 200 CC 20 XX 2 II 1000 M 100 C 10 X 1 I
咱们能够将他们的对应关系分为4组:
第一组,最高位小于4,他们对应的罗马数是叠加的,例如1000是M,3000是MMM
。
第二组,最高位等于4,他们对应的罗马数是在以5开头罗马数前加上以1开头的罗马数,且二者是相邻的关系。
第三组,最高位在5到8之间,对应的罗马数是以5开头的罗马数为基础,后跟上叠加的1开头的罗马数,二者也是相邻的关系。
第四组,最高为等于9,对应的罗马数是以1开头的罗马数间隔组合,例如900,在表明1000的M
前加表明100的C
,即CM
,二者中间间隔一位。
根据以上的对应关系组合,咱们将不一样整数、罗马数字符串初始化为数组,由高位到低位,依次计算罗马数。
public String intToRoman(int num) { String[] roman = {"M", "D", "C", "L", "X", "V", "I"}; int[] value = {1000, 500, 100, 50, 10, 5, 1}; StringBuilder sb = new StringBuilder(); for (int i=0; i<value.length; i+=2) { // 获得当前num的最高位 int tem = num/value[i]; if (tem < 4) { // 叠加 for (int j=0; j<tem; j++) { sb.append(roman[i]); } } else if (tem == 4) { // 相邻 sb.append(roman[i]+roman[i-1]); } else if (tem > 4 && tem < 9) { // 相邻 sb.append(roman[i-1]); for (int j=6; j<=tem; j++) { sb.append(roman[i]); } } else if (tem == 9) { // 间隔两位 sb.append(roman[i]+roman[i-2]); } // 去掉已经参与计算的高位 num = num%value[i]; } return sb.toString(); }
在第一种解法的基础上,咱们将初始数组中的元素分别对应增长了6位,以9和4开头。依旧是从高位往低位计算,与第一种解法中利用取余、取整不一样,此解法是循环作减法,直到num剩下的值小于当前须要减去的值,才会寻找下一个须要减去的数。
public String intToRoman2(int num) { String[] roman = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}; int[] value = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}; StringBuilder sb = new StringBuilder(); for (int i=0; i<value.length; i++) { while (num >= value[i]) { sb.append(roman[i]); num -= value[i]; } } return sb.toString(); }
还有一种取巧的解法。由于题目限定num的范围,最高不会超过4000,咱们能够把num拆成4个部分,千位只有四种可能,0(num是一个三位数)、一、二、3,百位对应的有10种可能,0到9,十位和个位也是10种可能,只须要将他们都列出来,依次取num中不一样位对应的字符串便可。
此解法的时间复杂度是O(1)
。
public static String intToRoman3(int num) { String M[] = {"", "M", "MM", "MMM"}; String C[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; String X[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; String I[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; return M[num/1000] + C[(num%1000)/100] + X[(num%100)/10] + I[num%10]; }
算法专题目前已连续日更超过六个月,算法题文章219+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。
以上就是所有内容,若是你们有什么好的解法思路、建议或者其余问题,能够下方留言交流,点赞、留言、转发就是对我最大的回报和支持!