ローマ数字を整数に

生田 陸人
LuaGate エンジニア / 現役エンジニア
編集 LuaGate編集部

ローマ数字を整数に

このレッスンで分かること

  • 減算表記 は「次の文字より自分が小さければ、自分を負として加える」と言い換えるだけで一発で解ける
  • ローマ数字I=1, V=5, X=10, L=50, C=100, D=500, M=1000 の 7 文字で 1 から 3999 までを表現します
  • 基本となる対応表は次の通りです

ローマ数字を整数に とは

IV, IX のような 減算表記 を含む ローマ数字 を、隣り合う 2 文字を見比べる 1 パス で整数に変換する。

ローマ数字I=1, V=5, X=10, L=50, C=100, D=500, M=1000 の 7 文字で 1 から 3999 までを表現します。IV = 4, IX = 9 のように、小さい数字が大きい数字の前に来たときは 減算表記 になる、というルールがあります。本レッスンは、この変換を 1 パス O(n) で実装します。

減算表記 は「次の文字より自分が小さければ、自分を負として加える」と言い換えるだけで一発で解ける。

ローマ数字の規則

基本となる対応表は次の通りです。

記号
I1
V5
X10
L50
C100
D500
M1000

減算表記 は次の 6 通りだけです。

  • IV = 4, IX = 9
  • XL = 40, XC = 90
  • CD = 400, CM = 900

1 パスで解くアイデア

左から見て、自分の値 < 次の文字の値 なら 自分を負 として足し、そうでなければ 自分を正 として足します。これだけで 減算表記通常表記 も統一的に処理できます。

diagram (will load when visible)

図のポイント (テキスト併記)

  • 例えば MCMXCIV (1994) なら、次のように処理します

例えば MCMXCIV (1994) なら、次のように処理します。

  • M(1000) >= C(100)+1000
  • C(100) < M(1000)-100
  • M(1000) >= X(10)+1000
  • X(10) < C(100)-10
  • C(100) >= I(1)+100
  • I(1) < V(5)-1
  • V(5) 末尾 → +5

合計は 1000 - 100 + 1000 - 10 + 100 - 1 + 5 = 1994 です。

Python での実装

Python

def romanToInt(s): values = {'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000} total = 0 n = len(s) for i in range(n): if i + 1 < n and values[s[i]] < values[s[i + 1]]: total -= values[s[i]] else: total += values[s[i]] return total

values で 1 文字 → 整数を引きます。あとは隣同士を比較するだけ。シンプルで、O(n) で完了します。

JavaScript での実装

JavaScript

function romanToInt(s) { const values = { I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000 }; let total = 0; for (let i = 0; i < s.length; i++) { if (i + 1 < s.length && values[s[i]] < values[s[i + 1]]) { total -= values[s[i]]; } else { total += values[s[i]]; } } return total; }

Java でも同じ発想です。Map<Character, Integer> を使うか、switch で値を引いてください。

別解: ペアでまず置換する方法

IV, IX, XL, XC, CD, CM の 6 ペアを先に 空文字 に置き換え、別途加算する方法もあります。一見シンプルですが、文字列の置換コストや順序ミスのリスクがあるため、1 パス 法のほうが事故が少ないです。

競プロや面接では、隣を見る 系のアルゴリズム発想に慣れておくと応用が効く。

減算表記 は中世以降に整理されたもので、古代ローマでは IIII = 4 のように愚直な書き方も普通にあった。今回扱うのは現代の規約。

よくある間違い

  • i + 1 < n のチェックを忘れて IndexError を出す。
  • values のキーを 小文字 で書いてしまい、大文字入力で KeyError
  • 減算加算 か迷ったとき、テストケース IX = 9 で確認すれば一発で分かる。

やってみよう

romanToInt(s) を実装してください。s1 から 3999 までを表す 有効なローマ数字文字列 です (不正な入力は来ません)。1 パス O(n) で整数を返してください。隣の文字を見て大小比較 という基本パターンは、他の問題でも応用が効くので、ぜひ手を動かして体に染み込ませましょう。

よくある質問

Q. このトピックは実務でどう役立ちますか?

A. DB のクエリ最適化、API 設計、データ構造の選択など、設計判断の根拠になります。表面的にライブラリを使うだけでなく「なぜそれが速いのか」を理解できると、性能問題を未然に防げます。コーディング面接でも頻出のテーマです。

Q. 計算量はどう求めれば良いですか?

A. ループのネストごとに掛け算する、再帰なら漸化式から解く、というのが基本です。Big-O 表記は定数倍と低次の項を無視するため、n の指数(n²、n log n など)に注目してください。最悪・平均・最良の 3 つを意識すると説得力が増します。

Q. 覚えるべき定番アルゴリズムは何ですか?

A. 二分探索、クイックソート/マージソート、BFS/DFS、ダイクストラ、DP の基本問題(フィボナッチ・ナップサック)が必修です。これらを「白紙から書ける」状態にすると、応用問題が一気に解けるようになります。

次のレッスン

次は 整数をローマ数字に で、IV, IX のような 減算表記 を含む ローマ数字 を、隣り合う 2 文字を見比べる 1 パス で整数に変換する を学びます。

事前確認 — 進む前に次の 3 つができることを確認しましょう。

  1. ローマ数字→整数 の要点を自分の言葉で説明できる
  2. このレッスンの最小コード (または操作手順) を見ずに書ける
  3. 練習問題やクイズで間違えた箇所を読み直して理解した

理解度チェック (30 秒)

Q. ローマ数字→整数 とは何か、1 文で説明してください。

この章のポイント

A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。

関連レッスン

要件

  1. 関数 romanToInt(s) を実装し、整数 (1〜3999) を返す
  2. 減算表記 (IV, IX, XL, XC, CD, CM) を正しく扱う
  3. O(n) で実装する (1 パス)

入出力例

test-cases.txt

romanToInt("I")1 romanToInt("III")3 romanToInt("IV")4 romanToInt("IX")9 romanToInt("LVIII")58 romanToInt("MCMXCIV")1994 romanToInt("MMMCMXCIX")3999

ヒント

main.py
main.py
学習モード

メモ

ローマ数字を整数に

⌘S で保存