【LeetCode-Easy】13. Roman to Integer
*これはLeetCodeの問題「13. Roman to Integer」の回答をメモした備忘録です。
問題
Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.
Symbol Value
I 1
V 5
X 10
L 50
C 100
D 500
M 1000
For example, 2 is written as II in Roman numeral, just two ones added together. 12 is written as XII, which is simply X + II. The number 27 is written as XXVII, which is XX + V + II.
Roman numerals are usually written largest to smallest from left to right. However, the numeral for four is not IIII. Instead, the number four is written as IV. Because the one is before the five we subtract it making four. The same principle applies to the number nine, which is written as IX. There are six instances where subtraction is used:
- I can be placed before V (5) and X (10) to make 4 and 9.
- X can be placed before L (50) and C (100) to make 40 and 90.
- C can be placed before D (500) and M (1000) to make 400 and 900.
Given a roman numeral, convert it to an integer.
ローマ数字は、I、V、X、L、C、D、M の 7 つの異なる記号で表されます。
たとえば、2 はローマ数字で II と書きますが、これは単に 2 つを足したものです。 12 は XII と書きます。これは単に X + II です。 27 という数字は XXVII、つまり XX + V + II と書きます。
ローマ数字は通常、左から右に最大から最小まで書かれます。ただし、4 という数字は III ではありません。代わりに、数字の 4 は IV と書かれます。 1 は 5 の前にあるので、それを引いて 4 になります。数字の 9 にも当てはまります。
同じ原理が、IX と書かれる減算が使用される例は 6 つあります。
- I を V (5) と X (10) の前に配置して 4 と 9 を作ることができます。
- X を L (50) と C (100) の前に置くと、40 と 90 になります。
- C を D (500) と M (1000) の前に配置して、400 と 900 を作成できます。
与えられたローマ数字を整数に変換してください。
例
Input: s = "III"
Output: 3
Input: s = "LVIII"
Output: 58
Input: s = "MCMXCIV"
Output: 1994
回答
Solutionsでvest votedだった回答。処理が早い。
const roman = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000,
};
function romanToInt(s: string): number {
const integers = s.split('').map(c => roman[c]);
return integers.reduce((acc, x, i) => x < integers[i+1] ? acc - x : acc + x, 0);
};
回答(解説メモあり)
const roman = {
I: 1,
V: 5,
X: 10,
L: 50,
C: 100,
D: 500,
M: 1000,
};
//romanを配列にして定義する
function romanToInt(s: string): number {
//romanToIntというfunctionは、number型で返される。この関数で使われる引数sはstring型である。
const integers = s.split('').map(c => roman[c]);
//ローマ数字sをsplitして、各文字をromanのオブジェクトで対応する値を返す。その配列をintegers(整数)に代入する。
return integers.reduce((acc, x, i) => x < integers[i+1] ? acc - x : acc + x, 0);
//integersの各要素を足し算する。accは累積値を表し、初期値0が設定されている。
//xはintegersの現在の要素を表している。
//iは現在の要素のindexを表している。
//x < integers[i+1]では、現在の要素が次の要素よりも小さいか評価している。
//小さかったら、accから現在の要素を減算する
//大きい、もしくはイコールだったらaccと現在の要素を加算する
};
s=IVの場合、IとVに分割して、romanオブジェクトのI=1、V=5に変換したものをintergersに入れる。
intergersには、
roman = {
I:1,
V:5
}
が入っている状態。accは初期値0で設定されていて、各要素に対してx < integers[i+1] ? acc - x : acc + xを実行した場合、"1が5よりも小さい"が真になるので、1-5が成立する。よって、返される値は4となる。
Map関数
- 元の配列から 「新しい配列」 を作る。
- 配列のすべての要素に対して、与えられた関数を実行する。その結果からなる新しい配列を生成する。
const array1: number[] = [1, 2, 3, 4, 5];
const array2: number[] = array1.map(value => value * 2);
console.log(array2);
//実行すると以下となる
[ 2, 4, 6, 8, 10 ]
Reduce関数
- 配列の中の全てのデータにアクセスして、1つの値に変換する関数。
- 第一引数には2つの引数「アキュムレーター(acc)」 と 「現在の値」 を取る。
- アキュムレータには、「初期値」もしくは「直前の処理で返された値」が入り、現在の値には「今現在処理している配列要素」が入る。
- 第二引数では、アキュムレータの初期値を指定する。
const array1 = [1, 2, 3, 4];
const initialValue = 0;
//初期値を0とする
const sumWithInitial = array1.reduce(
(accumulator, currentValue) => accumulator + currentValue,
//accumulatorには累積値が更新されていく。accに対して、currentValueを加算していく。
initialValue,
);
console.log(sumWithInitial);
// sumWithInitialには、全ての値を加算した整数が返される
// Expected output: 10
Discussion