羅馬數字包含以下七種字元:
I
,
V
,
X
,
L
,
C
,
D
和
M
。
字元 數值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
例如, 羅馬數字 2 寫做
II
,即為兩個并列的 1。12 寫做
XII
,即為
X
+
II
。 27 寫做
XXVII
, 即為
XX
+
V
+
II
。
通常情況下,羅馬數字中小的數字在大的數字的右邊。但也存在特例,例如 4 不寫做
IIII
,而是
IV
。數字 1 在數字 5 的左邊,所表示的數等于大數 5 減小數 1 得到的數值 4 。同樣地,數字 9 表示為
IX
。這個特殊的規則隻适用于以下六種情況:
-
可以放在I
(5) 和V
(10) 的左邊,來表示 4 和 9。X
-
可以放在X
(50) 和L
(100) 的左邊,來表示 40 和 90。C
-
可以放在C
(500) 和D
(1000) 的左邊,來表示 400 和 900。M
給定一個羅馬數字,将其轉換成整數。輸入確定在 1 到 3999 的範圍内。
示例 1:
輸入: "III"
輸出: 3
示例 2:
輸入: "IV"
輸出: 4
示例 3:
輸入: "IX"
|輸出: 9
示例 4:
輸入: "LVIII"
輸出: 58
解釋: C = 100, L = 50, XXX = 30, III = 3.
示例 5:
輸入: "MCMXCIV"
|輸出: 1994
解釋: M = 1000, CM = 900, XC = 90, IV = 4.
解決方案
方法一:
該方法是将羅馬數字的所有情況從小到大事前存儲在一個資料結構中,然後将字元串從頭到尾依次進行比對,每比對成功一個,就将比對成功的字元串從原字元串中删除,并将該字元串對應的值進行相加。但是需要注意的是,由于是從頭開始查找,對于CM,CD這種雙字元的特殊情況需要進行處理,即隻處理s.find()函數傳回值為0的情況。
class Solution {
public:
int romanToInt(string s) {
vector<int> v1{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
vector<string> v2{"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
int res = 0, pos = 0;
while(s != "")
{
if(s.find(v2[pos]) == 0)
{
res += v1[pos];
s = s.substr(v2[pos].size());
}
else
pos++;
}
return res;
}
};
方法二:
這是網上的解法,發現這樣子設計挺有意思的。我們需要用到map資料結構,來将羅馬數字的字母轉化為對應的整數值,因為輸入的一定是羅馬數字,那麼我們隻要考慮兩種情況即可:
第一,如果目前數字是最後一個數字,或者之後的數字比它小的話,則加上目前數字
第二,其他情況則減去這個數字
class Solution {
public:
int romanToInt(string s) {
int res = 0;
unordered_map<char, int> m{{'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000}};
for (int i = 0; i < s.size(); ++i) {
int val = m[s[i]];
if (i == s.size() - 1 || m[s[i+1]] <= m[s[i]]) res += val;
else res -= val;
}
return res;
}
};