Roman to Integer Conversion in DSA C - Time & Space Complexity
We want to know how the time to convert a Roman numeral to an integer changes as the input gets longer.
How does the number of steps grow when the Roman numeral string grows?
Analyze the time complexity of the following code snippet.
int romanToInt(char * s) {
int total = 0;
int i = 0;
while (s[i]) {
int current = value(s[i]);
int next = value(s[i + 1]);
if (next > current) {
total += (next - current);
i += 2;
} else {
total += current;
i++;
}
}
return total;
}
int value(char c) {
switch(c) {
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return 0;
}
}
This code converts a Roman numeral string to an integer by checking each character and sometimes the next one.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The while loop that goes through each character in the string.
- How many times: It runs once for each character, sometimes skipping one extra character when two are processed together.
As the Roman numeral string gets longer, the number of steps grows roughly the same as the string length.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 checks |
| 100 | About 100 checks |
| 1000 | About 1000 checks |
Pattern observation: The steps increase linearly with the input size.
Time Complexity: O(n)
This means the time to convert grows directly with the length of the Roman numeral string.
[X] Wrong: "Because we sometimes skip characters, the time is less than linear or constant."
[OK] Correct: Even when skipping, each character is still checked once, so the total work grows with the input size.
Understanding how to analyze simple loops like this helps you explain your code clearly and shows you know how input size affects performance.
"What if the input was given as a linked list of characters instead of a string? How would the time complexity change?"
Practice
Example: IV = 4, VI = 6Solution
Step 1: Understand Roman numeral rules
Roman numerals add values of symbols, but if a smaller symbol appears before a larger one, it is subtracted.Step 2: Apply rule to example
For IV, I (1) is before V (5), so subtract 1 from 5 = 4. For VI, V (5) before I (1), so add 5 + 1 = 6.Final Answer:
Add values of symbols, subtract if a smaller symbol is before a larger one -> Option BQuick Check:
IV = 4, VI = 6 [OK]
- Always adding without subtraction
- Multiplying symbols instead of adding
- Ignoring order of symbols
Solution
Step 1: Understand C array initialization for character keys
In C, to map characters to values, an array indexed by character offset is used, e.g., values['I'-'A'] = 1.Step 2: Check each option
int values[26] = {['I'-'A']=1, ['V'-'A']=5, ['X'-'A']=10}; uses correct syntax for sparse initialization. Options B and C use invalid syntax for C. int values[3] = {1, 5, 10}; initializes array without mapping to characters.Final Answer:
int values[26] = {['I'-'A']=1, ['V'-'A']=5, ['X'-'A']=10}; -> Option CQuick Check:
Correct C syntax for char-indexed array [OK]
- Using dictionary syntax not valid in C
- Not indexing array by character offset
- Initializing array without specifying indices
char *s = "MCMXCIV";
int values[26] = {['I'-'A']=1, ['V'-'A']=5, ['X'-'A']=10, ['L'-'A']=50, ['C'-'A']=100, ['D'-'A']=500, ['M'-'A']=1000};
int result = 0, i = 0;
while (s[i]) {
int curr = values[s[i]-'A'];
int next = values[s[i+1]-'A'];
if (next > curr) result -= curr;
else result += curr;
i++;
}
printf("%d", result);Solution
Step 1: Trace each character and apply addition/subtraction
String: M(1000), C(100), M(1000), X(10), C(100), I(1), V(5). Check pairs:
M(1000) next C(100) -> 100 < 1000? No, add 1000
C(100) next M(1000) -> 1000 > 100, subtract 100
M(1000) next X(10) -> 10 < 1000, add 1000
X(10) next C(100) -> 100 > 10, subtract 10
C(100) next I(1) -> 1 < 100, add 100
I(1) next V(5) -> 5 > 1, subtract 1
V(5) next 0, add 5Step 2: Calculate total
1000 - 100 + 1000 - 10 + 100 - 1 + 5 = 1994Final Answer:
1994 -> Option DQuick Check:
MCMXCIV = 1994 [OK]
- Adding all values without subtraction
- Off-by-one error accessing next character
- Incorrect mapping of Roman symbols
int romanToInt(char *s) {
int values[26] = {['I'-'A']=1, ['V'-'A']=5, ['X'-'A']=10, ['L'-'A']=50, ['C'-'A']=100, ['D'-'A']=500, ['M'-'A']=1000};
int result = 0, i = 0;
while (s[i]) {
int curr = values[s[i]-'A'];
int next = values[s[i+1]-'A'];
if (curr < next) result += curr;
else result -= curr;
i++;
}
return result;
}Solution
Step 1: Analyze addition and subtraction conditions
Code adds current value if curr < next, else subtracts. This is opposite of Roman rules where smaller before larger means subtract.Step 2: Correct logic
It should subtract curr if curr < next, else add curr.Final Answer:
The addition and subtraction logic is reversed -> Option AQuick Check:
Subtract when smaller before larger [OK]
- Swapping add and subtract conditions
- Ignoring last character's next value
- Not initializing values array properly
"XLIX", which of the following C functions correctly returns its integer value?Solution
Step 1: Check logic for subtraction and addition
int romanToInt(char *s) { int values[26] = {['I'-'A']=1, ['V'-'A']=5, ['X'-'A']=10, ['L'-'A']=50}; int res=0,i=0; while(s[i]) { int curr=values[s[i]-'A'], next=values[s[i+1]-'A']; if(currStep 2: Verify with example "XLIX"
X(10) < L(50) subtract 10
L(50) > I(1) add 50
I(1) < X(10) subtract 1
X(10) no next add 10
Total = -10 + 50 - 1 + 10 = 49Final Answer:
Option A correctly returns 49 for "XLIX" -> Option AQuick Check:
Subtract if smaller before larger [OK]
- Using <= instead of < for subtraction
- Adding all values without subtraction
- Incorrect comparison operators
Ready to prove it?
Pass the test and this pattern moves unknown
