Leetcode
  • Leetcode Questions
  • Runtime Screenshots
  • DataStructure
    • Leetcode 394. Decode String
    • Leetcode 225. Implement Stack Using Queues
    • Leetcode 336. Palindrome Pairs
    • Leetcode 316. Remove Duplicate Letters
    • Leetcode 206. Reverse Linked List
    • Leetcode 347. Top K Frequent Elements
    • Leetcode 227. Basic Calculator II
    • Leetcode 224. Basic Calculator
  • Linear
    • Leetcode 23. Merge k Sorted Lists
    • Leetcode 48. Rotate Image
    • Leetcode 6. ZigZag Conversion
    • Leetcode 438. Find All Anagrams in a String
    • Leetcode 189. Rotate Array
    • LeetCode 56. Merge Intervals
    • Leetcode 4. Median of Two Sorted Array
    • Leetcode 3. Longest Substring Without Repeating Characters
    • Leetcode 8. String to Integer (atoi)
    • Leetcode 5. Longest Palindromic Substring
    • Leetcode 11. Container With Most Water
  • Tree
    • Leetcode 103. Binary Tree Zigzag Level Order Traversal
    • Leetcode 508. Most Frequent Subtree Sum
    • Leetcode 226. Invert Binary Tree
    • Leetcode 222. Count Complete Tree Nodes
    • Leetcode 250. Count Univalue Subtrees
    • Leetcode 285. Inorder Successor in BST
    • Leetcode 230. Kth Smallest Element in a BST
    • Leetcode 543. Diameter of Binary Tree
    • Leetcode 199. Binary Tree Right Side View
  • Math
    • Leetcode 50. Power(x, n)
    • Leetcode 166. Fraction to Recurring Decimal
    • Leetcode 7. Reverse Integer
    • Leetcode 360. Sort Transformed Array
    • Leetcode 367. Valid Perfect Square
    • Leetcode 12. Integer to Roman
  • DynamicProgramming
    • Leetcode 10. Regular Expression Matching
    • Leetcode 253. Meeting Rooms II
    • Leetcode 303. Range Sum Query
    • Leetcode 22. Generate Parentheses
  • Graph
    • Leetcode 142. Linked List Cycle II
    • Leetcode 261. Graph Valid Tree
    • Leetcode 339. Nested List Weight Sum
    • Leetcode 207. Course Schedule
  • OODesign
    • Leetcode 295. Find Media From Data Stream
Powered by GitBook
On this page
  • Problem
  • Thoughts
  • Solution
  • Complexity Analysis
  • Extension
  • Summary
  • Reference

Was this helpful?

  1. Math

Leetcode 12. Integer to Roman

Problem

Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.

Symbol       Value
I             1
V             5
X             10
L             50
C             100
D             500
M             1000

For example, two is written as II in Roman numeral, just two one's added together. Twelve is written as, XII, which is simply X + II. The number twenty seven is written as XXVII, which is XX + V + II.

Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:

  • I can be placed before V (5) and X (10) to make 4 and 9.

  • X can be placed before L (50) and C (100) to make 40 and 90.

  • C can be placed before D (500) and M (1000) to make 400 and 900.

Given an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999.

Example 1:

Input: 3
Output: "III"

Example 2:

Input: 4
Output: "IV"

Example 3:

Input: 9
Output: "IX"

Example 4:

Input: 58
Output: "LVIII"
Explanation: L = 50, V = 5, III = 3.

Example 5:

Input: 1994
Output: "MCMXCIV"
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

Thoughts

However, I'd like to suggest an alternative solution that is more general and extensible. Assume some day magically we needs roman numerals to include a very large range of number (e.g. 1 - 99999) and we adds more symbols like "Y, Z, .." besides "X, L, C, D, M". Then it's obvious we shoudn't keep hard coding. That's not what we as programmers do.

Instead, we should optimally only code the RULES that converts integer to roman numerals, as following:

  • the conversion table: symbols (arbitrary large number) to values, e.g. X to 10 or C to 100.

  • general rule: largest to smallest from left to right, by adding symbols together.

  • exception: 4 and 9 case.

Besdies above RULES, the digit by digit conversion should be AUTOMATICALLY performed by computer.

Solution

This solution enables us to easily present arbitarily large range of number in "roman" numerals with new symbols. Instead of hard coding every digits, we only need to include new symbols in the lookup table. (My code should be further improved to be more concise).

In a more pratical sense, it's always good to show interviewers that you have a mindset for extensibility and maintainability.

class Solution {
    public String intToRoman(int num) {

        // Roman lookup table
        char[][] roman = {
            {'I', 'V'},
            {'X', 'L'},
            {'C', 'D'},
            {'M'}
        };

        StringBuilder res = new StringBuilder();
        int power = 0;
        final int ONE = 0; final int FIVE = 1;

        while (num > 0) {    
            int digit = num % 10;

            // Two exceptions of 4 and 9
            if (digit == 4) {
                res.insert(0, roman[power][FIVE]);
                res.insert(0, roman[power][ONE]);
            }

            else if (digit == 9) {
                res.insert(0, roman[power + 1][ONE]);
                res.insert(0, roman[power][ONE]);
            }

            // General rule for digit larger than 5
            else if (digit >= 5) {
                for (int i = 0; i < digit - 5; i++) {
                    res.insert(0, roman[power][ONE]);
                }
                res.insert(0, roman[power][FIVE]);
            }

            else { // digit < 5 and not four
                for (int i = 0; i < digit; i++) {
                    res.insert(0, roman[power][ONE]);
                }
            }

            num /= 10;
            power += 1;
        }

        return res.toString();
    }
}

Complexity Analysis

  • Time Complexity: O(k), where k equals to the number of digits input number have. We have to iterate all digits of the input number.

  • Space Complexity: O(1). No additional space is used except the output string builder.

Extension

Simplify the code to make it more readable and concise.

Summary

This question can surely be solved efficiently using brutal force. It's fast and it beats 100%. Nonetheless, these solutions lack the essense of programmic thinking. When we design an algorithm, we should not only care about solving it under given context, but also establishes foundations for future extension if requirement changes.

Reference

PreviousLeetcode 367. Valid Perfect SquareNextDynamicProgramming

Last updated 5 years ago

Was this helpful?

As had figured out, we can manually write out all ten roman digits for each of the ones, tens, hundreds, and thousands places. In this way we hard-coded 40ish digits and used only one line of "code". Admittedly, these hard coded solutions will work perfectly given that roman numerals only range from 1 to 3999.

those highly voted discussion posts
M's post on the discussion section