題目描述:將一個 1 到 3999 的整數轉換為羅馬數字字串。羅馬數字由 I、V、X、L、C、D、M 組合而成,並包含六個減法表示:IV=4、IX=9、XL=40、XC=90、CD=400、CM=900。
解題思路:這是一道貪心(Greedy)問題。羅馬數字的構造規則是:盡可能使用面值最大的符號,反覆減去已使用的面值,直到數字歸零。
預定義對照表:將所有值(包含減法組合)從大到小排列成配對陣列:
[(1000,"M"), (900,"CM"), (500,"D"), (400,"CD"),
(100,"C"), (90,"XC"), (50,"L"), (40,"XL"),
(10,"X"), (9,"IX"), (5,"V"), (4,"IV"), (1,"I")]
貪心流程:對每個配對,只要當前數字 num >= value,就不斷將對應符號拼接到結果字串,並從 num 中減去該面值。重複此過程直到 num == 0。
例如 num = 1994:先用 M(1000) 一次 → 994;再用 CM(900) 一次 → 94;再用 XC(90) 一次 → 4;再用 IV(4) 一次 → 0。結果為 "MCMXCIV"。
時間複雜度:O(1) — 對照表大小固定為 13 個配對,且輸入上限為 3999,每個符號最多被使用常數次(M 最多 3 次,其他更少),總迴圈次數有上界,屬常數時間。
空間複雜度:O(1) — 對照表大小固定,結果字串長度最長為 15 個字元(3999 = "MMMCMXCIX",9 個字元),均為常數空間。
1. Define valueSymbols as ordered list (descending): [(1000,"M"),(900,"CM"),(500,"D"),(400,"CD"),(100,"C"),(90,"XC"),(50,"L"),(40,"XL"),(10,"X"),(9,"IX"),(5,"V"),(4,"IV"),(1,"I")].
2. Initialize result as empty string.
3. For each (value, symbol) in valueSymbols:
a. While num >= value:
- Append symbol to result.
- Subtract value from num.
4. Return result.方法一:貪心 + 對照表(本題主解法) 如上所述,預先列出所有 13 個值-符號配對(含六個減法形式),從大到小貪心地選取符號。時間 O(1),空間 O(1),邏輯清晰,是最推薦的做法。
方法二:按位分解(Digit-by-Digit)
分別對千位、百位、十位、個位建立各自的羅馬字元對照表。例如千位:["" , "M", "MM", "MMM"];百位:["", "C", "CC", "CD", "D", "DC", "DCC", "DCCC", "CM"] 等。取出每一位數字後直接查表拼接,不需要迴圈。時間 O(1),空間 O(1),執行速度略快,但需要預先把所有組合硬編碼,程式碼較冗長。
方法三:遞迴
找到最大能整除的面值,遞迴處理餘數。intToRoman(num) = symbol + intToRoman(num - value)。思路直觀但有函數呼叫開銷,且 C++ 無尾遞迴最佳化保證,實用性不如迭代版本。