0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Leetcode 13. Roman to Integer Easyの解説

0
Posted at

問題:
https://leetcode.com/problems/roman-to-integer/
正解者さん:
https://leetcode.com/problems/roman-to-integer/discuss/965594/Python

正解の引用コード
class Solution(object):
    def romanToInt(self, s):
        rd = {
            "I" : 1,
            "V" : 5,
            "X" : 10,
            "L" : 50,
            "C" : 100,
            "D" : 500,
            "M" : 1000
        }
        
        n = len(s)
        rt = 0
        for i in range(n):
            if  i==n-1 or rd[s[i]] >= rd[s[i+1]] :
                rt += rd[s[i]]
            else :
                rt -= rd[s[i]]
                
        return rt

  
まず、
Input: s = "III"
Output: 3
とする。
  
  
次に、
rd = {
"I" : 1,
"V" : 5,
"X" : 10,
"L" : 50,
"C" : 100,
"D" : 500,
"M" : 1000
}
と書いてアルファベットと数字を関連付けた辞書を作る。
  
  
次に、
n = len(s)
で、sの中の要素数を数える
(n=3)
  
  
次に、
for i in range(n):
で、0,1,2がiに入っていく間に下のコードを実行する。
  
  
次に、
if i==n-1 or rd[s[i]] >= rd[s[i+1]] :
rt += rd[s[i]]
で、もしi(0)がn-1(2)の数字と同じ、
または、"III"の0番目であるrdの辞書内の要素("I"(1))が、"III"の0+1番目("I"(1))よりも大きいか同じだったら、
rt = 0に、{rt(0) + "III"の0番目であるrdの辞書内の要素("I"(1))}の値を入れる。
(rt = 1)
  
  
次に、
else :
rt -= rd[s[i]]
で、それ以外だったら{rt(0) - "III"の0番目であるrdの辞書内の要素("I"(1))}の値をrt = 0に入れる。
(rt = -1)
  
  
次に、
if i==n-1 or rd[s[i]] >= rd[s[i+1]] :
rt += rd[s[i]]
を繰り返す。
もしも 1が2と同じか、"III"の1番目であるrdの辞書内の要素("I"(1))が、"III"の1+1番目("I"(1))よりも大きいか同じだったら、
rt = 1に、{rt(1) + "III"の1番目であるrdの辞書内の要素("I"(1))}の値を入れる。
(rt = 2)
  
  
また、
if i==n-1 or rd[s[i]] >= rd[s[i+1]] :
rt += rd[s[i]]
を繰り返す。
もしも 2が2と同じか、"III"の2番目であるrdの辞書内の要素("I"(1))が、"III"の2+1番目("I"(1))よりも大きいか同じだったら、
rt = 2に、{rt(2) + "III"の1番目であるrdの辞書内の要素("I"(1))}の値を入れる。
(rt = 3)

次に、
for i in range(n):
を確認してみると、この時点でn(0,1,2)が全てiに入ってしまっているため、forループ文は終了する。
  
  
最後に、
return rt(3)
となり、正解にたどり着く。
  
  
  
  
別の値を入れてみよう。 
Input: s = "MCMXCIV"
Output: 1994
とする。

次に、
n = len(s)
で、sの中の要素数を数える
(n=7)
  
  
for i in range(n):
で、0,1,2,3,4,5,6がiに入っていく間に下のコードを実行する。
  
  
次に、
if i==n-1 or rd[s[i]] >= rd[s[i+1]] :
rt += rd[s[i]]
で、もしi(0)がn-1(6)の数字と同じ、
または、"MCMXCIV"の0番目であるrdの辞書内の要素("M"(1000))が、"MCMXCIV"の0+1番目("C"(100))よりも大きいか同じだったら、
rt = 0に、{rt(0) + "MCMXCIV"の0番目であるrdの辞書内の要素("M"(1000)}の値を入れる。
(rt = 1000)
  
  
次に、
if i==n-1 or rd[s[i]] >= rd[s[i+1]] :
rt += rd[s[i]]
を繰り返す。
今回は、1が6と同じか、"MCMXCIV"の1番目であるrdの辞書内の要素("C"(100))が、"MCMXCIV"の1+1番目("M"(1000))よりも大きいか同じではないので、
else :
rt -= rd[s[i]]
を使う。{rt(1000) - "MCMXCIV"の1番目であるrdの辞書内の要素("C"(100))}の値をrtに入れる。
(rt = 900)
  
  
次に、
if i==n-1 or rd[s[i]] >= rd[s[i+1]] :
rt += rd[s[i]]
で、もし2が6と同じ、
または、"MCMXCIV"の2番目であるrdの辞書内の要素("M"(1000))が、"MCMXCIV"の2+1番目("X"(10))よりも大きいか同じだったら、
rt = 900に、{rt(900) + "MCMXCIV"の2番目であるrdの辞書内の要素("M"(1000)}の値を入れる。
(rt = 1900)
  
  
と繰り返していく。(長いので省略)
  
  
今回の肝は、
・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.
という縛りをいかに解決するかである。
この縛りが無ければ、
rt += rd[s[i]]
を何回も繰り返して足し算すればいい。

しかし、これだと、IVのときは、VからIが引かれて4になるという引き算ができなくなる。
そのため、もしもIがVよりも小さかった場合、Iの値を合計から引く、つまり、後で足されるVの値から先にIを引いておく必要がある。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?