Convert a Roman Numeral to an Integer
Solve this Problems, convert it to its integer value. Roman numerals are normally written largest-to-smallest left to right — but six specific pairs (IV, IX, XL, XC, CD, CM) flip that: a smaller symbol placed just before a larger one means subtract instead of add.
Looking up each symbol's value with a chain of if/else comparisons works, but it's the kind of lookup a hash mapHash MapA data structure that maps keys to values with O(1) average lookup time, instead of scanning through a list or chain of comparisons. was built for: build the 7 symbol-to-value pairs once, and every subsequent lookup becomes a single O(1) step. The core trick — comparing each symbol's value against the one right after it — stays the same either way: if the current symbol is smaller than the next one, it's part of a subtractive pair.
Test Case 1:
Test Case 2:
Test Case 3:
Constraints
- ◆
1 ≤ s.length ≤ 15 - ◆
s is a valid Roman numeral in the range [1, 3999] - ◆
Symbols used: I(1), V(5), X(10), L(50), C(100), D(500), M(1000)
Try the Dry Run
Don't just read the solution — watch it execute, one step at a time.
| 1 | class Solution { |
| 2 | public int romanToInt(String s) { |
| 3 | Map<Character, Integer> values = new HashMap<>(); |
| 4 | values.put('I', 1); values.put('V', 5); values.put('X', 10); |
| 5 | values.put('L', 50); values.put('C', 100); values.put('D', 500); values.put('M', 1000); |
| 6 | int total = 0; |
| 7 | for (int i = 0; i < s.length(); i++) { |
| 8 | int current = values.get(s.charAt(i)); |
| 9 | if (i + 1 < s.length() && current < values.get(s.charAt(i + 1))) { |
| 10 | total -= current; |
| 11 | } else { |
| 12 | total += current; |
| 13 | } |
| 14 | } |
| 15 | return total; |
| 16 | } |
| 17 | } |
| 18 |
0Build a hash map of all 7 symbol values once (I=1, V=5, X=10, L=50, C=100, D=500, M=1000). Start total at 0.
Approach & Solutions
Brute Force — If/Else Chain Lookup
BruteFor each character, find its value with a chain of if/else comparisons (no map) — then look up the next character's value the same way, and compare the two to decide whether to add or subtract. Still O(n) overall, but every lookup repeats the same chain of comparisons instead of a single O(1) step, and adding a new symbol later means editing the chain in two places.
O(n)O(1)1class Solution {
2 public int romanToInt(String s) {
3 int total = 0;
4 for (int i = 0; i < s.length(); i++) {
5 int current = valueOf(s.charAt(i));
6 int next = (i + 1 < s.length()) ? valueOf(s.charAt(i + 1)) : 0;
7 if (current < next) {
8 total -= current;
9 } else {
10 total += current;
11 }
12 }
13 return total;
14 }
15
16 private int valueOf(char c) {
17 if (c == 'I') return 1;
18 if (c == 'V') return 5;
19 if (c == 'X') return 10;
20 if (c == 'L') return 50;
21 if (c == 'C') return 100;
22 if (c == 'D') return 500;
23 if (c == 'M') return 1000;
24 return 0;
25 }
26}Optimal — Hash Map Lookup
OptimalBuild a hash map of all 7 symbol values once, up front. Then walk the string a single time — each lookup is now O(1) instead of a repeated chain of comparisons, and the code stays clean and easy to extend. Same time complexity as the brute force, but simpler and faster in practice.
O(n)O(1)1class Solution {
2 public int romanToInt(String s) {
3 Map<Character, Integer> values = new HashMap<>();
4 values.put('I', 1); values.put('V', 5); values.put('X', 10);
5 values.put('L', 50); values.put('C', 100); values.put('D', 500); values.put('M', 1000);
6 int total = 0;
7 for (int i = 0; i < s.length(); i++) {
8 int current = values.get(s.charAt(i));
9 if (i + 1 < s.length() && current < values.get(s.charAt(i + 1))) {
10 total -= current;
11 } else {
12 total += current;
13 }
14 }
15 return total;
16 }
17}