13. Roman to Integer

練習日期:2026-02-08

難度:Easy

類型:Hash Table、Math、String

📘 題目敘述

給你一個羅馬數字字串 s,請把它轉換成整數並回傳。

羅馬數字使用下列七個不同的符號表示,並對應不同的數值:

  • I = 1
  • V = 5
  • X = 10
  • L = 50
  • C = 100
  • D = 500
  • M = 1000

例如 2 寫成 II,也就是 2 個 1 相加。12 寫成 XII,也就是 X + II

通常情況下,羅馬數字由左到右從大到小排列。但有六種特殊情況會用「減法表示」:

  • I 可以放在 V(5)和 X(10)前面,形成 IV(4)和 IX(9)
  • X 可以放在 L(50)和 C(100)前面,形成 XL(40)和 XC(90)
  • C 可以放在 D(500)和 M(1000)前面,形成 CD(400)和 CM(900)

題目保證 s 是一個有效的羅馬數字,範圍在 13999

條件限制

  • 1 <= s.length <= 15
  • s 只包含字元 ('I', 'V', 'X', 'L', 'C', 'D', 'M')
  • 題目保證 s 是有效的羅馬數字,範圍在 [1, 3999]

🧠 解題思路

這題最重要的地方是「減法表示」:像 IV 其實不是 1 + 5,而是 5 - 1

我用從左到右掃描的方式處理,並且只記住「上一個符號的值」就夠了。

我用 before 表示上一個羅馬符號的數值,now 表示目前這個符號的數值。每次讀到一個新符號後:

  • 一般情況:now <= before
    代表是正常的由大到小排列,我直接把 now 加到答案上。
  • 減法情況:now > before
    代表上一個符號其實應該要被減掉(例如 IV 讀到 Vnow=5before=1)。
    但我前一步其實已經把 before 加進 ans 了,所以現在要把它修正回「減法」效果:
    目標應該是:ans 這一段貢獻要變成 now - before
    但目前 ans 早就變成 ... + before + now
    所以我要做的修正是:再加上 -2 * before,也就是:
    ans = ans + now - 2 * before

這就是你程式裡那行的由來。

至於怎麼把字元轉成數值,我用兩個陣列 sym / val 做對照,每次遇到字元就去找它是哪個符號,拿到對應的值。

所有變數

  • now:目前掃到的羅馬符號對應的數值
  • before:上一個掃到的羅馬符號對應的數值
  • ans:累加後的整數答案
  • val:大小為 7 的陣列,依序存 I,V,X,L,C,D,M 的數值
  • sym:大小為 7 的陣列,依序存羅馬符號 I,V,X,L,C,D,M

🪜 主要流程步驟

1. 先準備羅馬符號對照表,並初始化狀態

我先用 sym / val 建立符號到數值的對應。然後把 ans 初始化為 0,並用 before = 10000 當作一個「比所有符號都大」的初始值,避免一開始就被判成減法。

2. 從左到右掃描字串,找出每個字元對應的數值 now

對每個字元 c,我用一個小迴圈去對照 sym,找到相同符號後就把 now = val[i] 設好,代表目前符號的數值。

3. 根據 nowbefore 判斷是正常加法還是減法修正

如果 now > before,代表出現像 IVIX 這種減法情況。因為上一輪已經把 before 加進 ans 了,所以我要用:
ans = ans + now - 2 * before
+before 修正成 -before

如果 now <= before,代表正常排列,直接做:
ans += now

4. 更新 before,準備處理下一個字元

每處理完一個字元,我就把 before = now,讓下一輪可以用它來判斷是否出現減法。

5. 回傳 ans

掃描結束後回傳答案。

💻 程式碼實作

class Solution {
public:
    int romanToInt(string s) {
        int now = 0, before = 10000;
        int ans = 0;
        int val[7] = {1, 5, 10, 50, 100, 500, 1000};
        char sym[7] = {'I', 'V', 'X', 'L', 'C', 'D', 'M'};
        for (char c : s) {
            for (int i = 0; i < 7; i++) {
                if (c == sym[i]) {
                    now = val[i];
                    if (now > before) {
                        ans = ans + now - 2 * before;
                    } else {
                        ans += now;
                    }
                    before = now;
                    break;
                }
            }
        }
        return ans;
    }
};

https://leetcode.com/problems/roman-to-integer/

作者:scottnick
撰寫日期:2026-02-08
類別:
原文連結:https://scottnick.github.io/cpp-notes/all%20problems/13-roman-to-integer.html