力扣面试经典算法150题:整数转罗马数字

44 篇文章 0 订阅
23 篇文章 0 订阅

整数转罗马数字

今天的题目是力扣面试经典150题中的数组的中等难度题: 整数转罗马数字。

题目链接:https://leetcode.cn/problems/integer-to-roman/description/?envType=study-plan-v2&envId=top-interview-150

题目描述

七个不同的符号代表罗马数字,其值如下:

符号
I1
V5
X10
L50
C100
D500
M1000

罗马数字是通过添加从最高到最低的小数位值的转换而形成的。

将小数位值转换为罗马数字有以下规则:

  • 如果该值不是以 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

题目分析

主要搞懂罗马字符和数字的转换逻辑就行。

前面做过简单题罗马字符转数字,这里反过来了,可以看看当时的题目是怎么解答的,帮助理解一下两者的转换。

传送门:罗马字符转数字

解题思路

罗马数字转换,我就想到一个暴力破解,无非就是暴力破解的时候转换值使用一点小技巧。

那么直接看代码吧。

实际算法代码

以下是暴力解答的代码实现:

public class IntegerToRoman {

    public static void main(String[] args) {
        IntegerToRoman solution = new IntegerToRoman();
        System.out.println(solution.intToRoman(3));       // 输出: "III"
        System.out.println(solution.intToRoman(4));       // 输出: "IV"
        System.out.println(solution.intToRoman(9));       // 输出: "IX"
        System.out.println(solution.intToRoman(94));       // 输出: "IX"
        System.out.println(solution.intToRoman(222));       // 输出: "IX"
        System.out.println(solution.intToRoman(666));       // 输出: "IX"
    }

    public String intToRoman(int num) {
        // 构建映射表
        int[][] map = {
                {1000, 500, 100, 50, 10, 5, 1},
                {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1}
        };
        String[][] romanMap = {
                {"M", "D", "C", "L", "X", "V", "I"},
                {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"}
        };

        StringBuilder sb = new StringBuilder();

        // 处理千位
        int thousands = num / 1000;
        while (thousands > 0) {
            sb.append(romanMap[0][0]);
            thousands--;
        }

        // 处理百位
        int hundreds = (num % 1000) / 100;
        while (hundreds > 0) {
            sb.append(romanMap[1][2]);
            hundreds--;
        }

        // 处理十位
        int tens = (num % 100) / 10;
        while (tens > 0) {
            sb.append(romanMap[1][4]);
            tens--;
        }

        // 处理个位
        int ones = num % 10;
        while (ones > 0) {
            sb.append(romanMap[1][6]);
            ones--;
        }

        // 优化特殊组合
        sb = optimize(sb);

        return sb.toString();
    }

    private StringBuilder optimize(StringBuilder sb) {
        // 优化特殊组合
        String s = sb.toString();
        StringBuilder optimized = new StringBuilder();

        // 处理千位
        optimized.append(s.replaceAll("DCCCC", "CM").replaceAll("CCCC", "CD"));

        // 处理百位
        optimized.append(s.replaceAll("LXXXX", "XC").replaceAll("XXXX", "XL"));

        // 处理十位
        optimized.append(s.replaceAll("VIIII", "IX").replaceAll("IIII", "IV"));

        return optimized;
    }

}

结果

执行程序,符合要求
在这里插入图片描述
提交力扣,通过测试:
在这里插入图片描述

总结

今天的题目就是暴力解答,主要还是逻辑问题。做了这么久题目肯定没问题,不行就参考一下字符转数字,中间有一点共通之处帮助更好的理解两者间的转换。

加油!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值