ローマ数字を整数に
ローマ数字を整数に
このレッスンで分かること
減算表記は「次の文字より自分が小さければ、自分を負として加える」と言い換えるだけで一発で解けるローマ数字は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) で実装します。
減算表記は「次の文字より自分が小さければ、自分を負として加える」と言い換えるだけで一発で解ける。
ローマ数字の規則
基本となる対応表は次の通りです。
| 記号 | 値 |
|---|---|
I | 1 |
V | 5 |
X | 10 |
L | 50 |
C | 100 |
D | 500 |
M | 1000 |
減算表記 は次の 6 通りだけです。
IV = 4,IX = 9XL = 40,XC = 90CD = 400,CM = 900
1 パスで解くアイデア
左から見て、自分の値 < 次の文字の値 なら 自分を負 として足し、そうでなければ 自分を正 として足します。これだけで 減算表記 も 通常表記 も統一的に処理できます。
図のポイント (テキスト併記)
- 例えば
MCMXCIV(1994) なら、次のように処理します
例えば MCMXCIV (1994) なら、次のように処理します。
M(1000)>=C(100)→+1000C(100)<M(1000)→-100M(1000)>=X(10)→+1000X(10)<C(100)→-10C(100)>=I(1)→+100I(1)<V(5)→-1V(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 totalvalues で 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) を実装してください。s は 1 から 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 つができることを確認しましょう。
- ローマ数字→整数 の要点を自分の言葉で説明できる
- このレッスンの最小コード (または操作手順) を見ずに書ける
- 練習問題やクイズで間違えた箇所を読み直して理解した
理解度チェック (30 秒)
Q. ローマ数字→整数 とは何か、1 文で説明してください。
A. 本文の「このレッスンで分かること」または冒頭の説明文を見直し、自分の言葉で要約できれば OK。詰まったら本レッスンの最初の H2 セクションを読み返してみましょう。
関連レッスン
要件
- 関数
romanToInt(s)を実装し、整数 (1〜3999) を返す 減算表記(IV,IX,XL,XC,CD,CM) を正しく扱う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