LeetCode -12-整数转罗马数字-题解

文章介绍了如何使用编程语言实现将1到3999之间的整数转换为罗马数字的算法,通过递归和分组处理不同范围内的数字组合,展示了Solution类中的intToRoman函数的详细步骤和逻辑.
摘要由CSDN通过智能技术生成

1. 问题描述

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

示例 1:

输入: num = 3
输出: "III"

示例 2:

输入: num = 4
输出: "IV"

示例 3:

输入: num = 9
输出: "IX"

示例 4:

输入: num = 58
输出: "LVIII"
解释: L = 50, V = 5, III = 3.

示例 5:

输入: num = 1994
输出: "MCMXCIV"
解释: M = 1000, CM = 900, XC = 90, IV = 4.

提示:

  • 1 <= num <= 3999

2. 思路分析

本题输入num范围在1-3999之间,由于可以用1,4,5,9,10,40,50,90,100,400,500,900,1000这13种数字对应的罗马符号来表示num,且当100<=num<1000&&num%100=0时,num可以由100,400,500,900这些数字组合;当10<=num<100&&num%10=0时,num可以由10,40,50,90这些数字组合;当1<=num<10时,num可以由1,4,5,9,这些数字组合;因此我们可以将这13种数字分成四组(其中1000单独一组)。例如1399=1000+300+90+9,我们可以这样拆成四部分,每部分分别去用对应部分的罗马数字组合表示,例如300这部分,可以从900开始遍历到100,当遍历的数字比300小时,就是我们要存的罗马符号,并让300=300-遍历的数字,然后继续遍历,以此类推。

3.算法描述

(1)键盘输入num,表示要转换成罗马数字的整数;
(2)Solution 类包含了一个 intToRoman 函数,该函数接受一个整数作为参数,并返回一个代表对应罗马数字的字符串。
(3)创建长度都为13的整型数组integer和字符串数组luoma,用来存13种整数和13种罗马符号

int integer[13]={1,4,5,9,10,40,50,90,100,400,500,900,1000};
string luoma[13]={"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"};


(4)创建字符串result用来返回结果
(5)用while循环来判断num的位数并使得mask=1eN(N为num的位数-1)

while(t>9){
            t/=10;
            mask*=10;
        }


(6)用if来单独判断num是否>1000,若>1000,则至少由几个1000组成,就将多少个“M”保存在字符串result中,并让num%=mask和mask/=10(mask是用来判断所要组合的数是属于哪个部分的)

if(mask==integer[12]){
            for(t=1;t<=num/mask;t++)result+=luoma[12];
            num%=mask;
            mask/=10;
        }


(7)用一个循环来判断剩余3个部分(由于其他部分是有规律的,4个数为一组),所以循环的条件以100,10,1为基准
(8)在循环体内创建sum来表示所要进行组合的那个部分的值,当mask遍历到等于对应的基准时,就继续用循环去用对应部分的4个数组合成sum,并将组合的罗马符号存到result中,然后这部分表示完成后,就继续num%=mask和mask/=10进入下一部分,以此类推直到每一部分都表达完成则返回result

注意:
(1)由于输出要求从大到小输出,所以每次遍历也都要从大到小
(2)当每部分遍历到最后一个数,即1 10 100时,若sum的值不为0,应让它继续与1 10 100相减直至sum为0,并依次将罗马符号存入result;例如某部分600,遍历完循环还剩下200,此时应继续让它去与100相减直至为0

while(sum!=0){
                    result+=luoma[x+1];
                    sum-=integer[x+1];
                }

4.完整代码实现
 

#include <iostream>
#include<string>
using namespace std;
class Solution {
public:
    string intToRoman(int num) {
        int integer[13]={1,4,5,9,10,40,50,90,100,400,500,900,1000};
        string luoma[13]={"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"};
        string result="";
        int mask=1,x;
        int t=num;
        while(t>9){
            t/=10;
            mask*=10;
        }
        if(mask==integer[12]){
            for(t=1;t<=num/mask;t++)result+=luoma[12];
            num%=mask;
            mask/=10;
        }
        for(t=8;t>=0;t-=4){
            int sum=num/mask*mask;
            if(mask==integer[t]){
                for(x=t+3;x>=t;x--){
                    if(sum>=integer[x]){
                        result+=luoma[x];
                        sum-=integer[x];
                    }
                }
                while(sum!=0){
                    result+=luoma[x+1];
                    sum-=integer[x+1];
                }
                num%=mask;
                mask/=10;
            }
        }
        return result;
    }
};
int main()
{
    Solution n;
    int num;
    cout<<"请输入一个整数(1-3999):";
    cin>>num;
    string romanNum = n.intToRoman(num);
    cout<<romanNum<<endl;
    return 0;
}

该程序的时间复杂度为 O(logN),其中 N 表示输入的整数。

5.平台提交通过截图

ps:还有很多更好更方便的解题思路,不足之处请多指教

  • 35
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值