力扣经典算法篇-15-整数转罗马数字(自顶向下逐步分解)
1、题干
七个不同的符号代表罗马数字,其值如下:
罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:
如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)。
只有 10 的次方(I, X, C, M)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式。
给定一个整数,将其转换为罗马数字。
示例 1:
输入:num = 3749
输出: “MMMDCCXLIX”
解释:
3000 = MMM 由于 1000 (M) + 1000 (M) + 1000 (M)
700 = DCC 由于 500 (D) + 100 © + 100 ©
40 = XL 由于 50 (L) 减 10 (X)
9 = IX 由于 10 (X) 减 1 (I)
注意:49 不是 50 (L) 减 1 (I) 因为转换是基于小数位
示例 2:
输入:num = 58
输出:“LVIII”
解释:
50 = L
8 = VIII
示例 3:
输入:num = 1994
输出:“MCMXCIV”
解释:
1000 = M
900 = CM
90 = XC
4 = IV
提示:
1 <= num <= 3999
2、解题
方法一(自顶向下,逐步分解)
上一题我们解答了罗马数字转数字,本题是相反的过程。可以根据数据的特征从上到下逐步分解处理。
转化规则结合题目可知,可以通过全局Map的形式存储起来。从最高位千位,在到百位,十位和个位逐步转化处理。
转化过程中,需要注意4和9的特殊转换,如果大于5还要注意添加1次5的转化,剩下的就逐个按照最小累加。
代码示例:
static Map<Integer, String> int2CharMap = new HashMap<Integer, String>() {{ // 映射存储put(1, "I");put(5, "V");put(10, "X");put(50, "L");put(100, "C");put(500, "D");put(1000, "M");put(4, "IV");put(9, "IX");put(40, "XL");put(90, "XC");put(400, "CD");put(900, "CM");}};static List<Integer> numList = new ArrayList<Integer>() {{ // 处理顺序add(1000);add(100);add(10);add(1);}};public static String intToRoman(int num) {StringBuilder builder = new StringBuilder();for (int i = 0; i < numList.size(); i++) {Integer tempNum = numList.get(i); // 待转化部分的权值int front = num / tempNum; // 整数部分为待转化的部分if (front > 0) {if (front == 4 || front == 9) {builder.append(int2CharMap.get(front * tempNum)); // 4和9的转换} else {if (front > 4) {builder.append(int2CharMap.get(tempNum * 5)); // 大于4,非9需要处理依次-5的信息front = front - 5;}for (int j = 0; j < front; j++) { // 之后的剩余按照最小补充builder.append(int2CharMap.get(tempNum));}}}num = num % tempNum; // 余数即剩下未处理的部分}return builder.toString();}
方法二(自顶向下,逐步分解)
除了按照千,百,十,个的逐步分解外,还可以按照递减的思路。从高到低向下处理,能处理多高就处理多高,处理不了在向下分析。思路和方法一类似,只不过向下的方式不一样。
如:2816,题干最大1000,就先处理1000的,处理1次,得到1个M,一共处理2次;在处理900,不足则跳过;在处理500,可以处理1次得到1个D…
代码示例:
static int[] values = new int[]{1000,900,500,400,100,90,50,40,10,9,5,4,1};static String[] strs = new String[]{"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};public static String intToRoman(int num) {StringBuilder builder = new StringBuilder();for (int i = 0; i < values.length; i++) {int value = values[i];String str = strs[i];while (num>=value){builder.append(str);num = num-value;}if(num==0){break;}}return builder.toString();}
向阳出发,Dare To Be!!!