Hey everyone! Mahdi Shamlou here — back with another LeetCode classic problem.
Today, we're going to solve LeetCode #12: Integer to Roman.
This problem is interesting because it helps us understand how to break a number into smaller parts and convert each part into its Roman numeral representation.
Let's get started!
1. Understanding the Problem
We are given an integer and need to convert it into a Roman numeral.
Roman numerals use seven basic symbols:
| Symbol | Value |
|---|---|
| I | 1 |
| V | 5 |
| X | 10 |
| L | 50 |
| C | 100 |
| D | 500 |
| M | 1000 |
However, Roman numerals also have some special combinations:
| Value | Roman Numeral |
|---|---|
| 4 | IV |
| 9 | IX |
| 40 | XL |
| 90 | XC |
| 400 | CD |
| 900 | CM |
For example:
- 80 = LXXX
- 90 = XC
- 400 = CD
- 900 = CM
The important point is that we should handle these special values instead of writing four repeated symbols.
2. My Approach
My first idea was to start with the largest possible value and gradually reduce the input number.
For example, imagine we have:
num = 1994 We can break it down like this:
1994 = 1000 + 900 + 90 + 4 Then convert each part:
1000 = M 900 = CM 90 = XC 4 = IV So the final result is:
MCMXCIV This gave me a simple idea:
- Store all Roman numeral values in descending order.
- Store their corresponding symbols in the same order.
- Divide the input number by each value.
- Add the corresponding symbol as many times as needed.
- Update the remaining number and continue.
3. Why Use a For Loop?
There are only 13 values we need to check:
values = [ 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 ] Because the number of values is fixed, I decided to use a for loop instead of a while loop.
We don't need an unlimited loop. We only need to check these 13 values.
For every value, we calculate how many times it fits into the remaining number:
count = num // values[i] Then we add the corresponding Roman symbol:
result += symbols[i] * count Finally, we update the remaining number:
num = num % values[i] This allows us to move to the next smaller value.
4. My Final Python Solution
Here is my final implementation:
class Solution: def intToRoman(self, num: int) -> str: values = [ 1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1 ] symbols = [ "M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I" ] result = "" for i in range(len(values)): count = num // values[i] result += symbols[i] * count num = num % values[i] if num == 0: break return result 5. How Does It Work?
Let's use 1994 as an example.
At each step, we divide the remaining number by the current value.
| Current Value | Remaining Number | Count | Added Symbol |
|---|---|---|---|
| 1000 | 1994 | 1 | M |
| 900 | 994 | 1 | CM |
| 500 | 94 | 0 | - |
| 400 | 94 | 0 | - |
| 100 | 94 | 0 | - |
| 90 | 94 | 1 | XC |
| 50 | 4 | 0 | - |
| 40 | 4 | 0 | - |
| 10 | 4 | 0 | - |
| 9 | 4 | 0 | - |
| 5 | 4 | 0 | - |
| 4 | 4 | 1 | IV |
The final result is:
MCMXCIV As you can see, we always process the largest possible value first.
6. Complexity Analysis
Let's analyze the solution.
Time Complexity: O(1)
We have only 13 predefined values, so the loop runs at most 13 times.
The number of iterations does not grow with the input number. Therefore, the time complexity is constant.
Space Complexity: O(1)
We use two fixed-size lists and a few variables.
The output string is also bounded because the input range in this problem is from 1 to 3999.
7. What Did I Learn?
This problem reminded me that choosing the right data structure and iteration strategy can make a solution very simple.
Instead of writing many conditions for different numbers, I used two lists:
- One for numeric values.
- One for their corresponding Roman symbols.
By keeping both lists in the same order, I could solve the problem with a single loop.
I also learned that special cases like 900, 400, 90, and 40 are important when converting numbers into Roman numerals.
Final Thoughts
This was a nice problem to practice working with arrays, integer division, modulo, and a greedy approach.
The solution is simple, readable, and efficient.
What would your approach be? Would you use a similar list-based solution, or would you try another way?
Let me know in the comments!
You can also find my LeetCode solutions in my GitHub repository:
GitHub: mahdi0shamlou/LeetCode
Author: Mahdi Shamlou
Author: مهدی شاملو

