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.
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