Roman to Integer Conversion
Given a string in roman form, the task is to convert this given roman string into an integer.
Roman numerals are based on the symbols I, V, X, L, C, D, and M, which represent 1, 5, 10, 50, 100, 500, and 1,000 respectively. Different arrangements of these symbols represent different numbers. The roman numbers I, II, III, IV, V, VI, VII, VIII, IX, and X represent 1, 2, 3, 4, 5, 6, 7, 8, 9 and 10 respectively.
How does the conversion work?
- If a smaller value symbol comes before, we subtract. Otherwise, we add.
- In IV, I comes before V and V has a larger value 5. So our result is 5 - 1 = 4.
- In VI, V comes before I and I has a smaller value 1. So our result is 5 + 1 = 6.
- In II, we have same values, so we add and get 1 + 1 = 2
- In case of more than 2 characters, we traverse from left to right and group only when we see a greater value character after a smaller value character. For example MXVII is 1000 + 10 + 5 + 1 + 1 = 1017. And XLVII is (50 - 10) + 5 + 1 + 1 = 47. Note that L is larger and comes after X.
Examples:
Input: s = "IX"
Output: 9
Explanation: IX is a Roman symbol which represents 10 - 1 = 9Input: s = "XL"
Output: 40
Explanation: XL is a Roman symbol which represents 50 - 10 = 40Input: s = "MCMIV"
Output: 1904
Explanation: M is 1000, CM is 1000 - 100 = 900, and IV is 4. So we have total as 1000 + 900 + 4 = 1904
Table of Content
[Expected Approach 1] Using Iterative Comparison - O(n) time and O(1) space
The idea for converting a Roman numeral to an integer is that, we have to traverse the string from left to right. For each symbol compare it with the next symbol (if it exists). If the current symbol is greater than or equal to the next symbol then add its value to the result. Otherwise, subtract its value from the next symbol's value and add the result to the total, and skip the next symbol.
#include <bits/stdc++.h>
using namespace std;
// This function returns value of a Roman symbol
int value(char r) {
if (r == 'I')
return 1;
if (r == 'V')
return 5;
if (r == 'X')
return 10;
if (r == 'L')
return 50;
if (r == 'C')
return 100;
if (r == 'D')
return 500;
if (r == 'M')
return 1000;
return -1;
}
// Returns decimal value of roman numeral
int romanToDecimal(string& s) {
int res = 0;
for (int i = 0; i < s.length(); i++) {
// Get value of current symbol
int s1 = value(s[i]);
// Compare with the next symbol if it exists
if (i + 1 < s.length()) {
int s2 = value(s[i + 1]);
// If current value is greater or equal, add it
// to result
if (s1 >= s2) {
res += s1;
}
else {
// Else, add the difference and skip next
// symbol
res += (s2 - s1);
i++;
}
}
else {
res += s1;
}
}
return res;
}
int main() {
string s = "IX";
cout << romanToDecimal(s) << endl;
return 0;
}
import java.util.*;
class GfG {
// This function returns value of a Roman symbol
static int value(char r) {
if (r == 'I')
return 1;
if (r == 'V')
return 5;
if (r == 'X')
return 10;
if (r == 'L')
return 50;
if (r == 'C')
return 100;
if (r == 'D')
return 500;
if (r == 'M')
return 1000;
return -1;
}
// Returns decimal value of roman numeral
static int romanToDecimal(String s) {
int res = 0;
for (int i = 0; i < s.length(); i++) {
// Get value of current symbol
int s1 = value(s.charAt(i));
// Compare with the next symbol if it exists
if (i + 1 < s.length()) {
int s2 = value(s.charAt(i + 1));
// If current value is greater or equal, add it
// to result
if (s1 >= s2) {
res += s1;
}
else {
// Else, add the difference and skip next
// symbol
res += (s2 - s1);
i++;
}
}
else {
res += s1;
}
}
return res;
}
public static void main(String[] args) {
String s = "IX";
System.out.println(romanToDecimal(s));
}
}
# This function returns value of a Roman symbol
def value(r):
if r == 'I':
return 1
if r == 'V':
return 5
if r == 'X':
return 10
if r == 'L':
return 50
if r == 'C':
return 100
if r == 'D':
return 500
if r == 'M':
return 1000
return -1
# Returns decimal value of roman numeral
def romanToDecimal(s):
res = 0
i = 0
while i < len(s):
# Get value of current symbol
s1 = value(s[i])
# Compare with the next symbol if it exists
if i + 1 < len(s):
s2 = value(s[i + 1])
# If current value is greater or equal,
# add it to result
if s1 >= s2:
res += s1
else:
# Else, add the difference and
# skip next symbol
res += (s2 - s1)
i += 1
else:
res += s1
i += 1
return res
if __name__ == "__main__":
s = "IX"
print(romanToDecimal(s))
using System;
class GfG {
// This function returns value of a Roman symbol
static int value(char r) {
if (r == 'I')
return 1;
if (r == 'V')
return 5;
if (r == 'X')
return 10;
if (r == 'L')
return 50;
if (r == 'C')
return 100;
if (r == 'D')
return 500;
if (r == 'M')
return 1000;
return -1;
}
// Returns decimal value of roman numeral
static int romanToDecimal(string s) {
int res = 0;
for (int i = 0; i < s.Length; i++) {
// Get value of current symbol
int s1 = value(s[i]);
// Compare with the next symbol if it exists
if (i + 1 < s.Length) {
int s2 = value(s[i + 1]);
// If current value is greater or equal, add it
// to result
if (s1 >= s2) {
res += s1;
}
else {
// Else, add the difference and skip next
// symbol
res += (s2 - s1);
i++;
}
}
else {
res += s1;
}
}
return res;
}
static void Main() {
string s = "IX";
Console.WriteLine(romanToDecimal(s));
}
}
// This function returns value of a Roman symbol
function value(r) {
if (r === 'I')
return 1;
if (r === 'V')
return 5;
if (r === 'X')
return 10;
if (r === 'L')
return 50;
if (r === 'C')
return 100;
if (r === 'D')
return 500;
if (r === 'M')
return 1000;
return -1;
}
// Returns decimal value of roman numeral
function romanToDecimal(s) {
let res = 0;
for (let i = 0; i < s.length; i++) {
// Get value of current symbol
let s1 = value(s[i]);
// Compare with the next symbol if it exists
if (i + 1 < s.length) {
let s2 = value(s[i + 1]);
// If current value is greater or equal, add it
// to result
if (s1 >= s2) {
res += s1;
}
else {
// Else, add the difference and skip next
// symbol
res += (s2 - s1);
i++;
}
}
else {
res += s1;
}
}
return res;
}
// Driver Code
let s = "IX";
console.log(romanToDecimal(s));
Output
9
Time Complexity: O(n), where n is the length of the string. Only one traversal of the string is required.
Auxiliary Space: O(1), As no extra space is required.
[Expected Approach 2] Using Hashing - O(n) time and O(1) space
We can use an hash map or dictionary to store the values of Roman symbols. And to solve the problem, we have to iterate through the string and for each symbol, check if the current value is less than the next value. If so, subtract the current value from the next value and add the result to the total. Otherwise, add the current value to the total.
#include <bits/stdc++.h>
using namespace std;
int romanToDecimal(string &s) {
unordered_map<char, int> romanMap = {{'I', 1}, {'V', 5},
{'X', 10}, {'L', 50},
{'C', 100}, {'D', 500},
{'M', 1000}};
int res = 0;
for (int i = 0; i < s.length(); i++) {
// If the current value is less than the next value,
// subtract current from next and add to res
if (i + 1 < s.length() && romanMap[s[i]] < romanMap[s[i + 1]]) {
res += romanMap[s[i + 1]] - romanMap[s[i]];
// Skip the next symbol
i++;
}
else {
// Otherwise, add the current value to res
res += romanMap[s[i]];
}
}
return res;
}
int main() {
string s = "IX";
cout << romanToDecimal(s) << endl;
return 0;
}
import java.util.HashMap;
class GfG {
static int romanToDecimal(String s) {
HashMap<Character, Integer> romanMap = new HashMap<>();
romanMap.put('I', 1);
romanMap.put('V', 5);
romanMap.put('X', 10);
romanMap.put('L', 50);
romanMap.put('C', 100);
romanMap.put('D', 500);
romanMap.put('M', 1000);
int res = 0;
for (int i = 0; i < s.length(); i++) {
// If the current value is less than the next value,
// subtract current from next and add to res
if (i + 1 < s.length() && romanMap.get(s.charAt(i)) <
romanMap.get(s.charAt(i + 1))) {
res += romanMap.get(s.charAt(i + 1)) -
romanMap.get(s.charAt(i));
// Skip the next symbol
i++;
}
else {
// Otherwise, add the current value to res
res += romanMap.get(s.charAt(i));
}
}
return res;
}
public static void main(String[] args) {
String s = "IX";
System.out.println(romanToDecimal(s));
}
}
def romanToDecimal(s):
romanMap = {'I': 1, 'V': 5, 'X': 10, 'L': 50,
'C': 100, 'D': 500, 'M': 1000}
res = 0
i = 0
while i < len(s):
# If the current value is less than the next value,
# subtract current from next and add to res
if i + 1 < len(s) and romanMap[s[i]] < romanMap[s[i + 1]]:
res += romanMap[s[i + 1]] - romanMap[s[i]]
# Skip the next symbol
i += 1
else:
# Otherwise, add the current value to res
res += romanMap[s[i]]
i += 1
return res
if __name__ == "__main__":
s = "IX"
print(romanToDecimal(s))
using System;
using System.Collections.Generic;
class GfG {
static int romanToDecimal(string s) {
// Create a map to store the Roman numeral values
Dictionary<char, int> romanMap = new Dictionary<char, int> {
{'I', 1}, {'V', 5}, {'X', 10}, {'L', 50},
{'C', 100}, {'D', 500}, {'M', 1000}
};
int res = 0;
for (int i = 0; i < s.Length; i++) {
// If the current value is less than the next value,
// subtract current from next and add to res
if (i + 1 < s.Length && romanMap[s[i]] < romanMap[s[i + 1]]) {
res += romanMap[s[i + 1]] - romanMap[s[i]];
// Skip the next symbol
i++;
}
else {
// Otherwise, add the current value to res
res += romanMap[s[i]];
}
}
return res;
}
static void Main() {
string s = "IX";
Console.WriteLine(romanToDecimal(s));
}
}
function romanToDecimal(s) {
// Create a map to store the Roman numeral values
const romanMap = {
'I': 1, 'V': 5, 'X': 10, 'L': 50,
'C': 100, 'D': 500, 'M': 1000
};
let res = 0;
for (let i = 0; i < s.length; i++) {
// If the current value is less than the next value,
// subtract current from next and add to res
if (i + 1 < s.length && romanMap[s[i]] < romanMap[s[i + 1]]) {
res += romanMap[s[i + 1]] - romanMap[s[i]];
// Skip the next symbol
i++;
}
else {
// Otherwise, add the current value to res
res += romanMap[s[i]];
}
}
return res;
}
// Main function
let s = "IX";
console.log(romanToDecimal(s));
Output
9
Time Complexity: O(n), where n is the length of the string and we have to iterate the string only once.
Auxiliary Space: O(1), As we are using a map of constant size, so the space complexity becomes O(1).