Integer to Roman Numeral + Reverse (Python)

Roman numerals contain the following seven characters: I, V, X, L, C, D, and M.

character value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

For example, the Roman numeral 2 is written as II, which is two parallel 1s. 12 is written as XII, which is X + II. 27 is written as XXVII, which is XX + V + II.
Normally, the smaller digits in Roman numerals are to the right of the larger digits. But there are also special cases, for example, 4 is not written as IIII, but IV. The number 1 is on the left of the number 5, and the represented number is equal to the value 4 obtained by reducing the number 1 from the large number 5. Likewise, the number 9 is expressed as IX. This particular rule applies only to the following six situations:

  • I can be placed to the left of V (5) and X (10) to represent 4 and 9.
  • X can be placed to the left of L (50) and C (100) to represent 40 and 90.
  • C can be placed to the left of D (500) and M (1000) to represent 400 and 900.

Given an integer, convert it to a Roman numeral. 1 <= num <= 3999.
Example 1:

Input: num = 3
Output: "III"

Example 2:

Input: num = 4
Output: "IV"

Example 3:

Input: num = 9
Output: "IX"

Example 4:

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

Example 5:

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

Idea 1: Greedy algorithm, use the larger Roman numerals as much as possible to match first, if the current number is greater than the current larger Roman numerals, get a Roman numeral. How to ensure that the current value is a larger Roman numeral: sort 13 (7+6) cases from large to small, and traverse them in turn.

def intToRoman(x):
    dic = {
    
    
        "M":1000,
        "CM":900,
        "D":500,
        "CD":400,
        "C":100,
        "XC":90,
        "L":50,
        "XL":40,
        "X":10,
        "IX":9,
        "V":5,
        "IV":4,
        "I":1
    }
    ronum = ""
    for key, value in dic.items():
        while x >= value and x > 0:
            x -= value
            ronum += key
    return ronum

There is also the if - else Dafa: not recommended, but the idea is actually like this.

def intToRoman(num):
        result = ""
        while num >= 1000:
            result += "M"
            num -= 1000
        if num >= 900:
            result += "CM"
            num-=900
        elif num >= 500:
            result += "D"
            num -= 500
        elif num >= 400:
            result += "CD"
            num -= 400

        while num >= 100:
            result += "C"
            num -= 100

        if num >= 90:
            result += "XC"
            num -= 90

        elif num >= 50:
            result += "L"
            num -= 50
        elif num >= 40:
            result += "XL"
            num -= 40

        while num >= 10:
            result += "X"
            num -= 10

        if num == 9:
            result += "IX"
            num -= 9;

        elif num >= 5:
            result += "V"
            num -= 5;

        elif num == 4:
            result += "IV"
            num -= 4

        while num >= 1:
            result += "I"
            num -= 1
        return result

Idea 2: Encoding, each number in the decimal representation of the integer num can be processed separately.

  • Thousands digits can only be represented by M;
  • Hundreds digits can only be represented by C, CD, D and CM;
  • Tens digits can only be represented by X, XL, L and XC;
  • Ones digits can only be represented by I, IV, V and IX.

insert image description here

def intToRoman(num):
    THOUSANDS = ["", "M", "MM", "MMM"]
    HUNDREDS = ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"]
    TENS = ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"]
    ONES = ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"]
    return THOUSANDS[num // 1000] + HUNDREDS[num % 1000 // 100] + TENS[num % 100 // 10] + ONES[num % 10]

Reverse: Convert Roman numerals to integers. Usually, the small number in Roman numerals is on the right of the large number.
Idea 1: Traverse the string, if the last digit is larger than the previous one, set a flag, skip the next traversed character (that is, the larger character), and add the corresponding value in the dictionary to the result; if the latter The bit is smaller than the previous one, just add it directly.

def romanToInt(s):
    dic = {
    
    
        "M":1000,
        "CM":900,
        "D":500,
        "CD":400,
        "C":100,
        "XC":90,
        "L":50,
        "XL":40,
        "X":10,
        "IX":9,
        "V":5,
        "IV":4,
        "I":1
    }
    flag = 0
    num = 0
    for i in range(len(s)):
        if flag:
            flag = 0
            continue
        if i < len(s)-1 and dic[s[i]] < dic[s[i+1]]:
            num += dic[s[i:i+2]]
            flag = 1  # 跳过下一次大罗马数字的遍历
        else:
            num += dic[s[i]]
    return num

Idea 2: There is no special rule in the dictionary. If there is a case where the small number is to the left of the large number, the small number needs to be subtracted according to the rules.

def romanToInt(s: str) -> int:
    dic = {
    
    
        'I': 1,
        'V': 5,
        'X': 10,
        'L': 50,
        'C': 100,
        'D': 500,
        'M': 1000,
    }
    ans = 0
    n = len(s)
    for i, ch in enumerate(s):  # 返回枚举index,value
        value = dic[ch]
        if i < n - 1 and value < dic[s[i + 1]]:
            ans -= value
        else:
            ans += value
    return ans

Guess you like

Origin blog.csdn.net/qq_43325582/article/details/122717805
Recommended