Skip to content

12. Integer to Roman

Seven different symbols represent Roman numerals with the following values:

Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

Roman numerals are formed by appending the conversions of decimal place values from highest to lowest. Converting a decimal place value into a Roman numeral has the following rules:

  • If the value does not start with 4 or 9, select the symbol of the maximal value that can be subtracted from the input, append that symbol to the result, subtract its value, and convert the remainder to a Roman numeral.
  • If the value starts with 4 or 9 use the subtractive form representing one symbol subtracted from the following symbol, for example, 4 is 1 (I) less than 5 (V): IV and 9 is 1 (I) less than 10 (X): IX. Only the following subtractive forms are used: 4 (IV), 9 (IX), 40 (XL), 90 (XC), 400 (CD) and 900 (CM).
  • Only powers of 10 (I, X, C, M) can be appended consecutively at most 3 times to represent multiples of 10. You cannot append 5 (V), 50 (L), or 500 (D) multiple times. If you need to append a symbol 4 times use the subtractive form.

Given an integer, convert it to a Roman numeral.

Example 1:

Input: num = 3749

Output: "MMMDCCXLIX"

Explanation:

3000 = MMM as 1000 (M) + 1000 (M) + 1000 (M)
 700 = DCC as 500 (D) + 100 (C) + 100 (C)
  40 = XL as 10 (X) less of 50 (L)
   9 = IX as 1 (I) less of 10 (X)
Note: 49 is not 1 (I) less of 50 (L) because the conversion is based on decimal places

Example 2:

Input: num = 58

Output: "LVIII"

Explanation:

50 = L
 8 = VIII

Example 3:

Input: num = 1994

Output: "MCMXCIV"

Explanation:

1000 = M
 900 = CM
  90 = XC
   4 = IV

Constraints:

  • 1 <= num <= 3999

Solution:

I = 1

II = 2

III = 3

IV = 4 (-1 + 5)

V = 5

VI = 6

VII = 7

VIII = 8

IX = 9 (- 1 + 10)

X = 10

...

L = 50

C = 100

D = 500

M = 1000

class Solution {
    public String intToRoman(int num) {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "I");
        map.put(4, "IV");
        map.put(5, "V");
        map.put(9, "IX");
        map.put(10, "X");
        map.put(40, "XL"); // (-10 + 50)
        map.put(50, "L");
        map.put(90, "XC"); 
        map.put(100, "C");
        map.put(400, "CD");
        map.put(500, "D");
        map.put(900, "CM");
        map.put(1000, "M");

        int[] values = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};

        StringBuilder sb = new StringBuilder();

        for (int v : values){
            while(num >= v){
                sb.append(map.get(v));
                num = num - v;
            }
        }
        return sb.toString();
    }

}

/*
Symbol  Value
I   1
V   5
X   10
L   50
C   100
D   500
M   1000

num = 3749
M        M.    M      D     C     C.    X   L    I.   X
1000 + 1000 + 1000 + 500 + 100 + 100 + 10 + 50 + 1 + 10

s

        f 
if ( f > s)  - > cur.   +  (f - 
*/

// TC: O(n)
// SC: O(1)
class Solution {
    public String intToRoman(int num) {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "I");
        map.put(4, "IV");
        map.put(5, "V");
        map.put(9, "IX");
        map.put(10, "X");
        map.put(40, "XL"); // (-10 + 50)
        map.put(50, "L");
        map.put(90, "XC"); 
        map.put(100, "C");
        map.put(400, "CD");
        map.put(500, "D");
        map.put(900, "CM");
        map.put(1000, "M");

        StringBuilder sb = new StringBuilder();
        int time = 1000;

      //  3749 
        while(time > 0){
            int curD = num;
            num = num;
            if (time != 0){
                curD = num / time; // 3749 /1000 = 3 
                num = num % time; // 749
            }

            if (curD == 0){
                time = time / 10;
                continue;

            }

          /*
          If the value does not start with 4 or 9, select the symbol of the maximal value that can be subtracted from the input, append that symbol to the result, subtract its value, and convert the remainder to a Roman numeral.
          */
            if (curD != 4 && curD != 9){
                if (curD == 5){
                    sb.append(map.get(5 * time));
                }

                if (curD < 4){
                    for (int i = 0; i < curD; i++){
                        sb.append(map.get(time));// 3 
                        // 1000 
                    }
                }

                if (curD > 5){
                    sb.append(map.get(5 * time));
                    for (int i = 0; i < curD - 5; i++){
                        sb.append(map.get(time));
                    }
                }
                time = time / 10;

            }

            if (curD == 4){
                sb.append(map.get(4 * time));
                time = time / 10;
                continue;
            }

            if (curD == 9){
                sb.append(map.get(9 * time));
                time = time / 10;
                continue;
            }

        }

        return sb.toString();
    }


}

/*
Symbol  Value
I   1
V   5
X   10
L   50
C   100
D   500
M   1000

num = 3749
M        M.    M      D     C     C.    X   L    I.   X
1000 + 1000 + 1000 + 500 + 100 + 100 + 10 + 50 + 1 + 10

s

        f 
if ( f > s)  - > cur.   +  (f - 
*/
class Solution {
    public String intToRoman(int num) {
        Map<Integer, String> map = new HashMap<>();
        map.put(1, "I");
        map.put(4, "IV");
        map.put(5, "V");
        map.put(9, "IX");
        map.put(10, "X");
        map.put(40, "XL"); // (-10 + 50)
        map.put(50, "L");
        map.put(90, "XC"); 
        map.put(100, "C");
        map.put(400, "CD");
        map.put(500, "D");
        map.put(900, "CM");
        map.put(1000, "M");

        StringBuilder sb = new StringBuilder();
        int time = 1000;

      //  3749 
        while(time > 0){
            int curD = num / time;
            num = num % time;

            if (curD == 0){
                time = time / 10;
                continue;

            }

            if (curD == 4){
                sb.append(map.get(4 * time));
                time = time / 10;
                continue;
            }else if (curD == 9){
                sb.append(map.get(9 * time));
                time = time / 10;
                continue;
            }else{
                if (curD >= 5){
                    sb.append(map.get(5 * time));
                    curD = curD - 5;
                }
                for (int i = 0; i < curD; i++){
                    sb.append(map.get(time));
                }
                time = time / 10;

            }

        }

        return sb.toString();
    }


}

// TC: O(n)
// SC: O(1)