題意
給兩個羅馬數字,要你用兩個羅馬數字輸出兩個絕對值。
羅馬數字的規則是:
I: 1
V: 5
X: 10
L: 50
C: 100
D: 500
M: 1000
從左往右把數字都加起來。如果有比較小的數字出現在比較大的數字之前則是要把他剪掉,例如: IV = 4, IX = 9。如果出現四個一樣的字母就要改用減法表示。
解題方法
這邊我把主要的功能都寫成 function,維持程式碼的簡潔。
羅馬數字轉十進位:
我先寫了一個把對應字母轉成數字的 function,接著再跑過一個迴圈,如果前面的數字比下一個大就把它減掉,反之就加上它,就可以把一串羅馬數字變成十進位了。
十進位轉羅馬數字:
我先直接把可能出現的排列都列出來: “M”, “CM”, “D”, “CD”, “C”, “XC”, “L”, “XL”, “X”, “IX”, “V”, “IV”, “I”。有些同學可能會擔心減法的部分會有很多種,但實際上就只有這些而已,大家可以仔細想想為甚麼。把他們都列好了之後,我們就可以貪心的從最大的開始拿,直到剩下的數字比現在的字母還小,就往下繼續拿。
#include <bits/stdc++.h>
using namespace std;
int f(char a){
if(a == 'I') return 1;
else if(a == 'V') return 5;
else if(a == 'X') return 10;
else if(a == 'L') return 50;
else if(a == 'C') return 100;
else if(a == 'D') return 500;
else if(a == 'M') return 1000;
return 0;
}
int romanToInt(string s) {
vector <int> a;
for(int i = 0;i < s.size();i++){
a.push_back(f(s[i]));
}
int sum = 0;
for(int i = 0;i < s.size();i++){
if(i < s.size() - 1 && a[i] < a[i+1]) sum -= a[i];
else sum += a[i];
}
return sum;
}
string intToRoman(int num) {
int val[13] = {1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1};
string ans[13] = {"M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"};
int p = 0;
string res = "";
while(num) { // 直到被拿成 0 之前都繼續
int cnt = num / val[p]; // 計算它最多可以拿幾個
for(int i = 0;i < cnt;i++) {
res += ans[p];
}
num -= val[p] * cnt;
p++;
}
return res;
}
int main(){
string a, b;
while(cin >> a) {
if(a == "#") break;
cin >> b;
int na = romanToInt(a), nb = romanToInt(b);
if(na == nb) cout << "ZERO\n";
else cout << intToRoman(abs(na - nb)) << '\n';
}
}
另外,Leetcode 上面有兩題都是裸的羅馬數字的題目,那邊的測試資料會比較強一點。想確認自己程式是否是對的同學可以去看看! 羅馬轉十進位 十進位轉羅馬
圖片來源:https://www.cuemath.com/numbers/roman-numerals-conversion/
發表迴響