題目
Given a roman numeral, convert it to aninteger.
Input is guaranteed to be within the rangefrom 1 to 3999.
輸入一個1-3999的羅馬數字(字符串),轉化成整型。
首先,我們要大致知道羅馬數字。
參考百度百科,主要本題要用的資料:
基本字符
I=1
V=5
X=10
L=50
C=100
D=500
M=1000
其他規則:
1、相同的數字連寫,所表示的數等於這些數字相加得到的數,如:Ⅲ = 3;
2、小的數字在大的數字的右邊,所表示的數等於這些數字相加得到的數,如:Ⅷ = 8;Ⅻ = 12;
3、小的數字,(限於Ⅰ、X 和C)在大的數字的左邊,所表示的數等於大數減小數得到的數,如:Ⅳ= 4;Ⅸ= 9;
4、正常使用時,連寫的數字重複不得超過三次。(錶盤上的四點鐘“IIII”例外)
我們可以發現,羅馬數字的字母是可以單個(i),成雙(ii / iv /vi),成三(iii / vii)計算的。那麼,我們在掃描字符的時候就要判斷,這個字符是獨立的,還是成對的,甚至是成三的。這樣的話問題有點複雜,我們得簡化一下。繼續觀察,這些非單的字符都是什麼聯繫,根據上面的規則1和2得知,同數連寫;大數接小數。這兩種情況下,只需要把每個數加起來就可以了,因此,這兩種情況實際上是單個數的算法,本質上是獨立的。
那麼就剩下規則3。小數接大數的時候,表示的數字是大數減小數,那麼,也就是隻有這種情況需要到兩個數參與運算。
思路:掃描羅馬數字字符串,我們設一箇中間值初始爲0,表示當前被掃描的字符的前一個字符所對應的值。如果當前字符大於前一個字符,那麼它屬於規則3的情況,因此運用減法,並且初始化中間值爲0。否則,只需要把中間值加到結果中,繼續往下掃描。最後返回結果。
圖示:
Leetcode的Accepted Solutions Runtime Distribution(截圖於5月上旬)
源碼:(VS2013)如果需要提交leetcode只需要把函數中的代碼複製過去即可。
#include <iostream>
#include <string>
#include <map>
using namespace std;
int transRoman(string s);
int main()
{
cout << transRoman("MCMXCVI");
return 0;
}
int transRoman(string s)
{
map<char, int> myMap;
myMap.insert(pair<char, int>('I', 1));
myMap.insert(pair<char, int>('V', 5));
myMap.insert(pair<char, int>('X', 10));
myMap.insert(pair<char, int>('L', 50));
myMap.insert(pair<char, int>('C', 100));
myMap.insert(pair<char, int>('D', 500));
myMap.insert(pair<char, int>('M', 1000));
int res = 0;
int temp = 0;
string::iterator iter = s.begin();//auto
string::iterator endIter = s.end();//auto
while (endIter != iter)//沒掃描到尾
{
int now = myMap.find(*iter)->second;//當前被掃描的字符對應的值
if (0 == temp)//中間值爲0,當前值作爲中間值。往後掃描
{
temp = now;
iter++;
}
else if (0 != temp && now > temp)
//當前值大於中間值,減法,並初始化中間值,往後掃描
{
res += (now - temp);
iter++;
temp = 0;
}
else if (0 != temp && now <= temp)
//當前值不大於中間值,把中間值加到結果中,設當前值爲中間值,往後掃描
{
res += temp;
temp = now;
iter++;
}
}
res += temp;//掃描到末尾了,記得加上最後一次的中間值(最後一個數)。
return res;
}