首页 > 代码库 > [LeetCode]Integer to Roman

[LeetCode]Integer to Roman

int型数字转化为罗马数字的形式

思路:

由于只是1到3999,一共只有四位,分别求这四位的情况。

可以将每一位从1到9,int和罗马数字的一一对应的关系给出来,然后直接转换。

/*****************************************************************
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
*****************************************************************/
#include <stdio.h>

char* intToRoman(int num) {
    int sd = num %10;
    int nm = num/10;
    int td = nm%10;
    nm /= 10;
    int hd = nm%10;
    nm /= 10;
    int thd = nm%10;
    int i,index = 0;
    char *rstr = (char *)malloc(16*sizeof(char));
    memset(rstr,0,16*sizeof(char));
    for(i = 0;i < thd;i++){
        rstr[index++] = M;
    }
    switch (hd)//百位
    {
        case 3://注意没有break
            rstr[index++] = C; 
        case 2://注意没有break
            rstr[index++] = C;
        case 1://注意没有break
            rstr[index++] = C;
            break;
        case 4://注意没有break
            rstr[index++] = C;
        case 5:
            rstr[index++] = D;
            break;
        case 6:
            rstr[index++] = D;
            rstr[index++] = C;
            break;
        case 7:
            rstr[index++] = D;
            rstr[index++] = C;
            rstr[index++] = C;
            break;
        case 8:
            rstr[index++] = D;
            rstr[index++] = C;
            rstr[index++] = C;
            rstr[index++] = C;
            break;
        case 9:
            rstr[index++] = C;
            rstr[index++] = M;
            break;
        default:
            break;
    }
    switch (td)//十位
    {
        case 3:
            rstr[index++] = X; 
        case 2:
            rstr[index++] = X;
        case 1:
            rstr[index++] = X;
            break;
        case 4:
            rstr[index++] = X;
        case 5:
            rstr[index++] = L;
            break;
        case 6:
            rstr[index++] = L;
            rstr[index++] = X;
            break;
        case 7:
            rstr[index++] = L;
            rstr[index++] = X;
            rstr[index++] = X;
            break;
        case 8:
            rstr[index++] = L;
            rstr[index++] = X;
            rstr[index++] = X;
            rstr[index++] = X;
            break;
        case 9:
            rstr[index++] = X;
            rstr[index++] = C;
            break;
        default:
            break;
    }
    switch (sd)//个位
    {
        case 3:
            rstr[index++] = I; 
        case 2:
            rstr[index++] = I;
        case 1:
            rstr[index++] = I;
            break;
        case 4:
            rstr[index++] = I;
        case 5:
            rstr[index++] = V;
            break;
        case 6:
            rstr[index++] = V;
            rstr[index++] = I;
            break;
        case 7:
            rstr[index++] = V;
            rstr[index++] = I;
            rstr[index++] = I;
            break;
        case 8:
            rstr[index++] = V;
            rstr[index++] = I;
            rstr[index++] = I;
            rstr[index++] = I;
            break;
        case 9:
            rstr[index++] = I;
            rstr[index++] = X;
            break;
        default:
            break;
    }
    return rstr;
}

int main(){
    int n = 1684;
    char *s = intToRoman(n);
    printf("%s\n",s);
    free(s);
    return 0;
}

上面思路代码冗余,不好。

思路2:

考虑每位对应数字是多少就先填多少个对应的罗马数字;

例如:46->XXXXIIIIII

然后多余的罗马数字在合。

合并的可能情况如下:

注意,每位都是一样的,用个位举例。

1.4个I合并为IV;IIII->IV

2.5个I合并为V;IIIII->V

3.2个V合并为X;IIIIIIIII->VIIII->VIV->IX

 1 /*****************************************************************
 2 Given an integer, convert it to a roman numeral.
 3 Input is guaranteed to be within the range from 1 to 3999.
 4 *****************************************************************/
 5 #include <stdio.h>
 6 
 7 char* intToRoman(int num) {
 8     char *rstr = (char *)malloc(32*sizeof(char));
 9     memset(rstr,0,32*sizeof(char));
10     char lromans[] = {M,C,X,I};
11     char uromans[] = { ,D,L,V};
12     int count = 0,lcount = 0,up = 0;
13     int i,k = 1000,index = 0,sum = 0;
14     while(num > 0){//在rstr数组中填充num的每位的数值对应数量的单位量字母(如num=9,则rstr="IIIIIIIII")
15         up = num/k;
16         num = num%k;
17         for(i = 0;i < up;i++){
18             rstr[sum++] = lromans[count];//填充
19         }
20         count++;
21         k = k/10;
22     }
23 
24     count = 0;
25     for(i = 0;i < sum;i++){//将每位的数值对应数量的单位量字母转换成正确的表示法
26         rstr[index] = rstr[i];
27         if(rstr[i] == lromans[count]){
28             lcount++;
29         }else{
30             do{
31                 count++;
32             }while(rstr[i] != lromans[count]);
33             lcount = 1;
34         }
35         if(lcount == 4){//4个的情况:IIII->IV
36             index -= 2;
37             rstr[index] = uromans[count];
38         }else if(lcount == 5){//5个的情况:IIIII->V
39             index -= 2;
40             rstr[index] = uromans[count];
41         }else if(lcount == 9){//9个的情况:IIIIIIIII->VIIII->VIV->IX
42             index -= 4;
43             rstr[index++] = lromans[count];
44             rstr[index] = lromans[count - 1];
45         }
46         index++;
47     }
48     rstr[index] = \0;
49 
50     return rstr;
51 }
52 
53 int main(){
54     int n = 3999;
55     char *s = intToRoman(n);
56     printf("%s\n",s);
57     free(s);
58     return 0;
59 }

思路3:

贪心算法:尽量从大单位开始匹配,但是4和9要特殊考虑。

/*****************************************************************
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.
*****************************************************************/
#include <stdio.h>

//找钱的思想,对4和9特殊处理,贪心算法
char* intToRoman(int num) {
    int weights[] = {1000,500,100,50,10,5,1};
    char romans[] = {M,D,C,L,X,V,I};
    int nums[7] = {0};
    char *rstr = (char *)malloc(16*sizeof(char));
    memset(rstr,0,16*sizeof(char));
    int i = 0,j = 0,index = 0;
    while(num > 0){
        nums[i] = num/weights[i];//记录罗马数字每个单位对应的字母的个数
        num = num%weights[i];
        i++;
    }
    for(i = 0;i < 7;i++){
        if(nums[i] == 4){//低位的单位有4个的时候可以转化的高位单位:IIII->IV
            nums[i] = 1;
            nums[i - 1]++;
            if(nums[i - 1] > 1){//两个以上的高位单位可以进位:VIV->IX
                rstr[index - 1] = romans[i];
                rstr[index++] = romans[i - 2];
            }else{
                rstr[index++] = romans[i];
                rstr[index++] = romans[i - 1];
            }
        }else{
            for(j = 0;j < nums[i];j++){
                rstr[index++] = romans[i];
            }
        }
    }
    return rstr;
}

int main(){
    int n = 3999;
    char *s = intToRoman(n);
    printf("%s\n",s);
    free(s);
    return 0;
}

 

[LeetCode]Integer to Roman