โจทย์ปัญหา
แปลง Roman Numeral String (1-3999) เป็น Integer
กฎการอ่านเลขโรมัน
- สัญลักษณ์: I=1, V=5, X=10, L=50, C=100, D=500, M=1000
- ปกติ: บวกค่าทั้งหมด (VI = 5+1=6)
- Subtractive Notation: ตัวเล็กหน้าตัวใหญ่ = ลบ (IV = 5-1=4, IX = 10-1=9, XL = 50-10=40, XC = 100-10=90, CD = 500-100=400, CM = 1000-100=900)
ตัวอย่าง
Input: "MCMIV"
Output: 1904
Breakdown: M(1000) + CM(900) + IV(4) = 1904
แนวคิดการแก้ปัญหา
掃描 String จากซ้ายไปขวา:
- ดูค่าตัวปัจจุบัน (
s1) และตัวถัดไป (s2) - ถ้า
s1 >= s2→ บวกs1 - ถ้า
s1 < s2→ บวกs2 - s1และข้ามตัวถัดไป (i++) - ตัวสุดท้ายเสมอ → บวกค่าตัวนั้น
โค้ดตัวอย่าง (C++)
#include <bits/stdc++.h>
using namespace std;
int romanValue(char r) {
switch (r) {
case 'I': return 1;
case 'V': return 5;
case 'X': return 10;
case 'L': return 50;
case 'C': return 100;
case 'D': return 500;
case 'M': return 1000;
default: return -1;
}
}
int romanToDecimal(string& str) {
int result = 0;
for (int i = 0; i < str.length(); i++) {
int s1 = romanValue(str[i]);
if (i + 1 < str.length()) {
int s2 = romanValue(str[i + 1]);
if (s1 >= s2) {
result += s1;
} else {
result += s2 - s1;
i++; // Skip next character
}
} else {
result += s1;
}
}
return result;
}
int main() {
string str = "MCMIV";
cout << "Integer form: " << romanToDecimal(str) << endl;
// Test cases
vector<string> tests = {"III", "IV", "IX", "LVIII", "MCMXCIV", "MMMCMXCIX"};
for (const string& s : tests) {
cout << s << " = " << romanToDecimal(const_cast<string&>(s)) << endl;
}
return 0;
}
ผลลัพธ์
Integer form: 1904
III = 3
IV = 4
IX = 9
LVIII = 58
MCMXCIV = 1994
MMMCMXCIX = 3999
Complexity Analysis
- Time: O(n) (n = ความยาว String)
- Space: O(1)
คำอธิบายเพิ่มเติม
- อัลกอริทึม Single Pass - อ่านครั้งเดียวจบ
- ใช้
unordered_mapแทน Switch ได้สำหรับ Extensibility - Validation: ควรตรวจสอบ Invalid Roman Numerals (เช่น "IIII", "VX") ถ้าจำเป็น
- ฟังก์ชันคู่: Integer to Roman (Article 1004080907)