《C语言》罗马数字问题
一.罗马数字
罗马数字是最早的数字表示方式,比阿拉伯数字早2000多年,起源于罗马。
如今我们最常见的罗马数字就是钟表的表盘符号:Ⅰ, Ⅱ , Ⅲ ,Ⅳ(IIII),Ⅴ ,Ⅵ ,Ⅶ ,Ⅷ ,Ⅸ ,Ⅹ ,Ⅺ ,Ⅻ ……
对应阿拉伯数字(就是现在国际通用的数字),就是1,2,3,4,5,6,7,8,9,10,11,12。(注:阿拉伯数字其实是古代印度人发明的,后来由阿拉伯人传入欧洲,被欧洲人误称为阿拉伯数字。)
基本字符 |
I |
V |
X |
L |
C |
D |
M |
相应的阿拉伯数字表示为 |
1 |
5 |
10 |
50 |
100 |
500 |
1000 |
相同的数字连写,所表示的数等于这些数字相加得到的数,如:Ⅲ = 3;
小的数字在大的数字的右边,所表示的数等于这些数字相加得到的数, 如:Ⅷ = 8;Ⅻ = 12;
小的数字,(限于Ⅰ、X 和C)在大的数字的左边,所表示的数等于大数减小数得到的数,如:Ⅳ= 4;Ⅸ= 9;
正常使用时,连写的数字重复不得超过三次。(表盘上的四点钟“IIII”例外)(注:现使用IV代表4)
在一个数的上面画一条横线,表示这个数扩大1000倍。
二. 罗马数字转整数(Roman to Integer)
1.思路:
一般来说,罗马数字中小的数字在大的数字的右边。那么只需要累加就可以。
例如:XVI 可视作 X+V+I=10+5+1=16;
若存在数字小的在大的数字左边的情况,我们需要根据规则减去小的数字。
例如:XIV 可视作 X-I+V=10-1+5=14.
#include#includemain(){ char s[] = "XVI"; //定义了一个字符串 int symbolvalues[26]; //26为数组的长度,因为一共26个英文字母所以大小不超过26 symbolvalues['I' - 'A'] = 1; symbolvalues['V' - 'A'] = 5; symbolvalues['X' - 'A'] = 10; symbolvalues['L' - 'A'] = 50; symbolvalues['C' - 'A'] = 100; symbolvalues['D' - 'A'] = 500; symbolvalues['M' - 'A'] = 1000; int sum = 0; int n = strlen(s); //n为字符串s的长度 for (int i = 0; i < n; i++) { int number = symbolvalues[s[i] - 'A']; //先找一个数字作为后续判断的标准 if (i < n - 1 && number < symbolvalues[s[i + 1] - 'A']) { sum -= number; //如果数字小的在大的数字左边的情况则相减 } else sum += number; } printf("%d", sum);}
2.习题练习 :https://leetcode-cn.com/problems/roman-to-integer/https://leetcode-cn.com/problems/roman-to-integer/
以下几种方法核心思路一样
代码1:
int romanToInt(char * s){int symbolvalues[26]; //共26个英文字母其大小不超过26,所以数组长度为26symbolvalues['I'-'A']=1;symbolvalues['V'-'A']=5;symbolvalues['X'-'A']=10;symbolvalues['L'-'A']=50;symbolvalues['C'-'A']=100;symbolvalues['D'-'A']=500;symbolvalues['M'-'A']=1000;int sum=0;int n=strlen(s); //n为字符串s的长度for(int i=0;i<n;i++){ int number=symbolvalues[s[i]-'A']; //定义number是为了与symbolvalues[s[i+1]-'A']作比较 if(i<n-1&&number<symbolvalues[s[i+1]-'A']) {sum-=number;} else sum+=number;}return sum;}
代码2.
int romanToInt(char * s){int sum= 0;while (*s){ //当出现I、X、C三个字符时,如果右边是对应的特殊情况,就相应减法。if (*s == 'V') sum += 5;//当不是特殊情况时,直接加法即可以else if (*s == 'L') sum += 50;else if (*s == 'D') sum += 500;else if (*s == 'M') sum += 1000;else if (*s == 'I')sum = (*(s + 1) == 'V' || *(s + 1) == 'X') ? sum - 1 : sum + 1;else if (*s == 'X')sum = (*(s + 1) == 'L' || *(s + 1) == 'C') ? sum - 10 : sum + 10;else if(*s=='C')sum = (*(s + 1) == 'D' || *(s + 1) == 'M') ? sum - 100 : sum + 100;s++;}return sum;}
三.整数转罗马数字(Integer to Roman)
1.思路:先举生活一个小栗子:在以前还使用现金购物的时候,找零钱的时候一般商家会尽量选择面值大的纸币(硬币)给顾客,这样才会使得给顾客的纸币(硬币)张数最少,让顾客点钱的时候更方便。
为了表示给的的整数num,我们寻找不超过num的最大符号值,将num减去该符号值,并用该符号拼接(下面代码所用的strcpy,或者也可以用strcat)在上一个找到的符号之后,循环直到为0的时候结束过程。
建立一个数值-符号对的列表valueSymbols,(类似于哈希表)
按数值从大到小排列。遍历valueSymbols中的每个数值-符号对,若当前数值value不超过num,则从num中不断减去value,直至num小于value,然后遍历下一个数值-符号对。若遍历中num为0则跳出循环。
例如:16
1.16<1000 16<900……1610,刚好对应symbols的X,故16-10=6;
2.65,故6-5=1,
3.1<4,继续遍历1=1 1-1=0结果为0,跳出循环。
所以16=X+V+Ⅰ。
代码如下
#include#include#include#pragma warning(disable:4996)main(){ int values[] = { 1000,900,500,400,100,90,50,40,10,9,5,4,1 }; //定义了一个整数数组 char* symbols[] = { "M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I" }; //罗马数字数组 int num = 16; //假设num为16,当然可以定义为其他的数字 char* roman = malloc(sizeof(char) * 16); //开辟了一个字符数组 roman[0] = '\0'; //字符数组初始化 for (int i = 0; i = values[i]) { num -= values[i]; strcpy(roman + strlen(roman), symbols[i]);//strcpy表示将字符复制到另一个字符里 } if (num == 0) //如果num为0说明所有罗马数字已经都变换完成 { break; } } for (int i = 0; i<strlen(roman); i++) { printf("%c", roman[i]); }}
2. 习题练习 :https://leetcode-cn.com/problems/integer-to-roman/https://leetcode-cn.com/problems/integer-to-roman/
代码1.
char * intToRoman(int num){int values[]={1000,900,500,400,100,90,50,40,10,9,5,4,1};char *symbols[]={"M","CM","D","CD","C","XC","L","XL","X","IX","V","IV","I"};char*Roman=(char*)malloc(sizeof(char)*25);Roman[0]='\0';for(int i=0;i=values[i]) { num-=values[i]; strcat(Roman,symbols[i]);//strcat为了字符的连接 // strcpy(Roman+strlen(Roman),symbols[i]); 或者使用strcpy if(num==0)break; }}return Roman;}
代码2.
比如输入是 2341
,我们找到 2000
,300
,40,1,而得到2000,300,40,1的方法就是利用取余
char * intToRoman(int num){ char* thousands[] = {"", "M", "MM", "MMM"}; char* hundreds[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; char* tens[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; char* ones[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"};char*roman=(char*)malloc(sizeof(char)*16);roman[0]='\0';strcpy(roman+strlen(roman),thousands[num/1000]);strcpy(roman+strlen(roman),hundreds[num%1000/100]);strcpy(roman+strlen(roman),tens[num%1000%100/10]);strcpy(roman+strlen(roman),ones[num%1000%100%10]);return roman;}