博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LeetCode_12_整数转罗马数字
阅读量:3951 次
发布时间:2019-05-24

本文共 2885 字,大约阅读时间需要 9 分钟。

文章目录

题目

罗马数字包含以下七种字符: 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 到 3999 的范围内。

在这里插入图片描述

思路一:彻底分解

刚开始想着将num彻底分解,得出num和各个数的商、余数,然后建立数学关系来得出最终的结果。

#include "string.h"char * intToRoman(int num){
const char const roman_numerals[8]={
'I','V','X','L','C','D','M'}; char *output_numerals=NULL; int preprocess[15]={
0}, leve[]={
0,1000,500,100,50,10,5,1}, i, j;//预处理结果存储和级别 j=1; /* 预处理num,得到num关于罗马数字所有的系数 */ for( i=1; i<7; i++ ){
preprocess[j] = num/leve[i]; preprocess[j+1] = num%leve[i]; j = j+2; num = preprocess[j]; } /* 进行数制转换 */ }

写着写着不行了,分解不开,寻求另一种解法。

思路二:贪心算法

程序如下:

char * intToRoman(int num){
char roman_number[][2]={
"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}; int leve[]={
1000,900,500,400,100,90,50,40,10,9,5,4,1}; char *result; int i=0, j=0, k=0; i = num/leve[0]; /* 先将可能超出1000的部分处理 */ if(i>0){
for( j=0; j

出现报错:Address Sanitizer: SEGV on unknown address 0x02007428cac2 (pc 0x00000040247e bp 0x7ffd0a52b010 sp 0x7ffd0a52b000 T0)

原因是:段错误,段错误是指访问的内存超过了系统所给这个程序的内存空间。这里返回的指针指向内容的是函数的栈,在函数调用完毕之后就会释放栈中的数据,所以返回时段错误。

所以尝试着用static char *result;来修饰返回值的指针,但是这样返回的值是NULL,因为虽然指向返回值的指针是存储在函数的静态存储区的,函数结束后也不会销毁静态存储区的局部变量的值,但是这个静态存储区指针指向的地址却随着函数执行完毕销毁了。

采用动态分配,再堆上申请一段空间来专门存放,代码如下:

char *result = (char*)malloc(100*sizeof(char));memset(result, 0, 100 * sizeof(char));

现在代码如下:

char * intToRoman(int num){
char roman_number[13][2]={
"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}; int i, leve[13]={
1000,900,500,400,100,90,50,40,10,9,5,4,1}; char *result = (char*)malloc(100*sizeof(char)); memset(result, 0, 100 * sizeof(char)); for( i=0; i<13; ){
if( num>=leve[i] ){
strcat( result, roman_number[i]); num -= leve[i]; } else{
i++;//采用这里的i++,来实现num的同一leve重复计算操作 } } return result;}

结果是:

在这里插入图片描述

分析原因之后发现,是我的roman_number字符串数组出问题了,没有考虑到系统自己加的‘\0’结束符,所以需要更改为:char roman_number[13][3]

修改之后代码为:

char * intToRoman(int num){
char roman_number[13][3]={
"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"}; int i, leve[13]={
1000,900,500,400,100,90,50,40,10,9,5,4,1}; char *result = (char*)malloc(100*sizeof(char)); memset(result, 0, 100 * sizeof(char)); for( i=0; i<13; ){
if( num>=leve[i] ){
strcat( result, roman_number[i]); num -= leve[i]; } else{
i++; } } return result;}

通过测试:

在这里插入图片描述

转载地址:http://xvwzi.baihongyu.com/

你可能感兴趣的文章
JAVA系统属性之user.home
查看>>
Android代码截屏
查看>>
Android中打印代码的调用层次
查看>>
成功者十三个价值连城的习惯
查看>>
特别成功的人会做6件事
查看>>
Android: 用jni 获取MAC地址
查看>>
字符串列表的C语言实现:c_strlist
查看>>
客户沟通的方式:礼貌待客沟通方式,技巧推广沟通方式,个性服务沟通方式
查看>>
用弹性工作制留住员工
查看>>
知识=经验×反思2
查看>>
领导者如何发现关键问题
查看>>
学习无为领导力
查看>>
卓越领导看过程
查看>>
领导力与各种循环挑战
查看>>
达成谈判协议 - 避免操之过急
查看>>
销售人说话“十大忌”
查看>>
营销中的“战略非对称”
查看>>
android 如何开关Mediatek开发的Feature
查看>>
Android电话功能各部分深入探讨
查看>>
Android应用技巧总结
查看>>