Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 8db22c1

Browse files
LeetCode problem: 12. Integer to Roman
1 parent d32e63d commit 8db22c1

File tree

3 files changed

+319
-0
lines changed

3 files changed

+319
-0
lines changed
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
# 12. Integer to Roman
2+
3+
Difficulty: `Medium`
4+
Topics: `Hash Table`, `Math`, `String`
5+
6+
Roman numerals are represented by seven different symbols: `I`, `V`, `X`, `L`, `C`, `D` and `M`.
7+
8+
```text
9+
Symbol Value
10+
I 1
11+
V 5
12+
X 10
13+
L 50
14+
C 100
15+
D 500
16+
M 1000
17+
```
18+
19+
For example, `2` is written as `II` in Roman numeral, just two ones added together. `12` is written as `XII`, which is
20+
simply `X + II`. The number `27` is written as `XXVII`, which is `XX + V + II`.
21+
22+
Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not `IIII`.
23+
Instead, the number four is written as `IV`. Because the one is before the five we subtract it making four. The same
24+
principle applies to the number nine, which is written as `IX`. There are six instances where subtraction is used:
25+
26+
- `I` can be placed before `V` (5) and `X` (10) to make 4 and 9.
27+
- `X` can be placed before `L` (50) and `C` (100) to make 40 and 90.
28+
- `C` can be placed before `D` (500) and `M` (1000) to make 400 and 900.
29+
30+
Given an integer, convert it to a roman numeral.
31+
32+
**Example 1:**
33+
34+
```text
35+
Input: num = 3
36+
Output: "III"
37+
Explanation: 3 is represented as 3 ones.
38+
```
39+
40+
**Example 2:**
41+
42+
```text
43+
Input: num = 58
44+
Output: "LVIII"
45+
Explanation: L = 50, V = 5, III = 3.
46+
```
47+
48+
**Example 3:**
49+
50+
```text
51+
Input: num = 1994
52+
Output: "MCMXCIV"
53+
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.
54+
```
55+
56+
**Constraints:**
57+
58+
- `1 <= num <= 3999`
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package com.bl.integer_to_roman;
2+
3+
/**
4+
* This is the solution to the LeetCode problem: 12. Integer to Roman
5+
*
6+
* @author Børre A. Opedal Lunde
7+
* @since 2024年01月27日
8+
*/
9+
public class Solution {
10+
11+
// This class stores the Roman numeral and its corresponding integer value.
12+
// (First I used a map, but the solution became really clumsy.)
13+
private static class RomanNumeral {
14+
15+
private final int value;
16+
private final String numeral;
17+
18+
public RomanNumeral(final int number, final String symbol) {
19+
this.value = number;
20+
this.numeral = symbol;
21+
}
22+
23+
// No getters are needed because it's a private inner class.
24+
}
25+
26+
// The Roman numerals are sorted in descending order because we want to
27+
// start with the largest and subtract our way down.
28+
private static final RomanNumeral[] ROMAN_NUMERALS = {
29+
new RomanNumeral(1000, "M"),
30+
new RomanNumeral(900, "CM"),
31+
new RomanNumeral(500, "D"),
32+
new RomanNumeral(400, "CD"),
33+
new RomanNumeral(100, "C"),
34+
new RomanNumeral(90, "XC"),
35+
new RomanNumeral(50, "L"),
36+
new RomanNumeral(40, "XL"),
37+
new RomanNumeral(10, "X"),
38+
new RomanNumeral(9, "IX"),
39+
new RomanNumeral(5, "V"),
40+
new RomanNumeral(4, "IV"),
41+
new RomanNumeral(1, "I")
42+
};
43+
44+
public String intToRoman(int num) {
45+
46+
// It is faster to use a string builder than a string.
47+
final StringBuilder builder = new StringBuilder();
48+
49+
// Go through every Roman numeral and subtract our way down, while
50+
// appending the Roman numeral to the string builder.
51+
for (final RomanNumeral romanNumeral : ROMAN_NUMERALS) {
52+
while (num >= romanNumeral.value) {
53+
num -= romanNumeral.value;
54+
builder.append(romanNumeral.numeral);
55+
}
56+
}
57+
return builder.toString();
58+
}
59+
}
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
package com.bl.integer_to_roman;
2+
3+
import org.junit.jupiter.api.DisplayName;
4+
import org.junit.jupiter.api.Test;
5+
import org.junit.jupiter.params.ParameterizedTest;
6+
import org.junit.jupiter.params.provider.Arguments;
7+
import org.junit.jupiter.params.provider.MethodSource;
8+
9+
import java.util.stream.Stream;
10+
11+
import static org.junit.jupiter.api.Assertions.assertEquals;
12+
13+
/**
14+
* This is the test to the LeetCode problem: 12. Integer to Roman
15+
*
16+
* @author Børre A. Opedal Lunde
17+
* @since 2024年01月27日
18+
*/
19+
@DisplayName("Integer to Roman")
20+
class SolutionTest {
21+
22+
final Solution solution = new Solution();
23+
24+
@Test
25+
@DisplayName("Example one")
26+
void exampleOne() {
27+
int num = 3;
28+
String expected = "III";
29+
String actual = solution.intToRoman(num);
30+
assertEquals(expected, actual);
31+
}
32+
33+
@Test
34+
@DisplayName("Example two")
35+
void exampleTwo() {
36+
int num = 58;
37+
String expected = "LVIII";
38+
String actual = solution.intToRoman(num);
39+
assertEquals(expected, actual);
40+
}
41+
42+
@Test
43+
@DisplayName("Example three")
44+
void exampleThree() {
45+
int num = 1994;
46+
String expected = "MCMXCIV";
47+
String actual = solution.intToRoman(num);
48+
assertEquals(expected, actual);
49+
}
50+
51+
static Stream<Arguments> providePrincipalNumbers() {
52+
return Stream.of(
53+
Arguments.of(1, "I"),
54+
Arguments.of(5, "V"),
55+
Arguments.of(10, "X"),
56+
Arguments.of(50, "L"),
57+
Arguments.of(100, "C"),
58+
Arguments.of(500, "D"),
59+
Arguments.of(1000, "M")
60+
);
61+
}
62+
63+
@ParameterizedTest(name = "Number {0} is Roman numeral {1}")
64+
@DisplayName("Principal Roman numbers")
65+
@MethodSource("providePrincipalNumbers")
66+
void principalRomanNumerals(int num, String expected) {
67+
String actual = solution.intToRoman(num);
68+
assertEquals(expected, actual);
69+
}
70+
71+
static Stream<Arguments> provideSubtractiveNumbers() {
72+
return Stream.of(
73+
Arguments.of(4, "IV"),
74+
Arguments.of(9, "IX"),
75+
Arguments.of(40, "XL"),
76+
Arguments.of(90, "XC"),
77+
Arguments.of(400, "CD"),
78+
Arguments.of(900, "CM")
79+
);
80+
}
81+
82+
@ParameterizedTest(name = "Number {0} is Roman numeral {1}")
83+
@DisplayName("Subtractive Roman numbers")
84+
@MethodSource("provideSubtractiveNumbers")
85+
void subtractiveRomanNumerals(int num, String expected) {
86+
String actual = solution.intToRoman(num);
87+
assertEquals(expected, actual);
88+
}
89+
90+
static Stream<Arguments> provideNumbersFromOneToOneHundred() {
91+
return Stream.of(
92+
Arguments.of(1, "I"),
93+
Arguments.of(2, "II"),
94+
Arguments.of(3, "III"),
95+
Arguments.of(4, "IV"),
96+
Arguments.of(5, "V"),
97+
Arguments.of(6, "VI"),
98+
Arguments.of(7, "VII"),
99+
Arguments.of(8, "VIII"),
100+
Arguments.of(9, "IX"),
101+
Arguments.of(10, "X"),
102+
Arguments.of(11, "XI"),
103+
Arguments.of(12, "XII"),
104+
Arguments.of(13, "XIII"),
105+
Arguments.of(14, "XIV"),
106+
Arguments.of(15, "XV"),
107+
Arguments.of(16, "XVI"),
108+
Arguments.of(17, "XVII"),
109+
Arguments.of(18, "XVIII"),
110+
Arguments.of(19, "XIX"),
111+
Arguments.of(20, "XX"),
112+
Arguments.of(21, "XXI"),
113+
Arguments.of(22, "XXII"),
114+
Arguments.of(23, "XXIII"),
115+
Arguments.of(24, "XXIV"),
116+
Arguments.of(25, "XXV"),
117+
Arguments.of(26, "XXVI"),
118+
Arguments.of(27, "XXVII"),
119+
Arguments.of(28, "XXVIII"),
120+
Arguments.of(29, "XXIX"),
121+
Arguments.of(30, "XXX"),
122+
Arguments.of(31, "XXXI"),
123+
Arguments.of(32, "XXXII"),
124+
Arguments.of(33, "XXXIII"),
125+
Arguments.of(34, "XXXIV"),
126+
Arguments.of(35, "XXXV"),
127+
Arguments.of(36, "XXXVI"),
128+
Arguments.of(37, "XXXVII"),
129+
Arguments.of(38, "XXXVIII"),
130+
Arguments.of(39, "XXXIX"),
131+
Arguments.of(40, "XL"),
132+
Arguments.of(41, "XLI"),
133+
Arguments.of(42, "XLII"),
134+
Arguments.of(43, "XLIII"),
135+
Arguments.of(44, "XLIV"),
136+
Arguments.of(45, "XLV"),
137+
Arguments.of(46, "XLVI"),
138+
Arguments.of(47, "XLVII"),
139+
Arguments.of(48, "XLVIII"),
140+
Arguments.of(49, "XLIX"),
141+
Arguments.of(50, "L"),
142+
Arguments.of(51, "LI"),
143+
Arguments.of(52, "LII"),
144+
Arguments.of(53, "LIII"),
145+
Arguments.of(54, "LIV"),
146+
Arguments.of(55, "LV"),
147+
Arguments.of(56, "LVI"),
148+
Arguments.of(57, "LVII"),
149+
Arguments.of(58, "LVIII"),
150+
Arguments.of(59, "LIX"),
151+
Arguments.of(60, "LX"),
152+
Arguments.of(61, "LXI"),
153+
Arguments.of(62, "LXII"),
154+
Arguments.of(63, "LXIII"),
155+
Arguments.of(64, "LXIV"),
156+
Arguments.of(65, "LXV"),
157+
Arguments.of(66, "LXVI"),
158+
Arguments.of(67, "LXVII"),
159+
Arguments.of(68, "LXVIII"),
160+
Arguments.of(69, "LXIX"),
161+
Arguments.of(70, "LXX"),
162+
Arguments.of(71, "LXXI"),
163+
Arguments.of(72, "LXXII"),
164+
Arguments.of(73, "LXXIII"),
165+
Arguments.of(74, "LXXIV"),
166+
Arguments.of(75, "LXXV"),
167+
Arguments.of(76, "LXXVI"),
168+
Arguments.of(77, "LXXVII"),
169+
Arguments.of(78, "LXXVIII"),
170+
Arguments.of(79, "LXXIX"),
171+
Arguments.of(80, "LXXX"),
172+
Arguments.of(81, "LXXXI"),
173+
Arguments.of(82, "LXXXII"),
174+
Arguments.of(83, "LXXXIII"),
175+
Arguments.of(84, "LXXXIV"),
176+
Arguments.of(85, "LXXXV"),
177+
Arguments.of(86, "LXXXVI"),
178+
Arguments.of(87, "LXXXVII"),
179+
Arguments.of(88, "LXXXVIII"),
180+
Arguments.of(89, "LXXXIX"),
181+
Arguments.of(90, "XC"),
182+
Arguments.of(91, "XCI"),
183+
Arguments.of(92, "XCII"),
184+
Arguments.of(93, "XCIII"),
185+
Arguments.of(94, "XCIV"),
186+
Arguments.of(95, "XCV"),
187+
Arguments.of(96, "XCVI"),
188+
Arguments.of(97, "XCVII"),
189+
Arguments.of(98, "XCVIII"),
190+
Arguments.of(99, "XCIX"),
191+
Arguments.of(100, "C")
192+
);
193+
}
194+
195+
@ParameterizedTest(name = "Number {0} is Roman numeral {1}")
196+
@DisplayName("Roman numerals from one to one hundred")
197+
@MethodSource("provideNumbersFromOneToOneHundred")
198+
void romanNumeralsFromOneToOneHundred(int num, String expected) {
199+
String actual = solution.intToRoman(num);
200+
assertEquals(actual, expected);
201+
}
202+
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /