---
# System prepended metadata

title: 13. Roman to Integer
tags: [Leetcode]

---

# 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` 是一個有效的羅馬數字，範圍在 `1` 到 `3999`。

### 條件限制

* `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` 讀到 `V` 時 `now=5`、`before=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. 根據 `now` 和 `before` 判斷是正常加法還是減法修正

如果 `now > before`，代表出現像 `IV`、`IX` 這種減法情況。因為上一輪已經把 `before` 加進 `ans` 了，所以我要用：

`ans = ans + now - 2 * before`

把「+before」修正成「-before」。

如果 `now <= before`，代表正常排列，直接做：

`ans += now`

---

### 4. 更新 `before`，準備處理下一個字元

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

### 5. 回傳 `ans`

掃描結束後回傳答案。

## 💻 程式碼實作

```cpp
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/description/