modalsoul’s blog

これは“失敗”と呼べるかもしれないが、ぼくは“学習体験”と呼びたい

LeetCode 13. Roman to Integer

LeetCode Problem No.13.

No.12 is here.

modalsoul.hatenablog.com

13. Roman to Integer

Roman numerals are represented by seven different symbols: I, V, X, L, C, D and M.

Given a roman numeral, convert it to an integer.

Example 1

Input: s = "III"
Output: 3
Explanation: III = 3.

Example 2

Input: s = "LVIII"
Output: 58
Explanation: L = 50, V= 5, III = 3.

Example 3

Input: s = "MCMXCIV"
Output: 1994
Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

Constraints

1 <= s.length <= 15
s contains only the characters ('I', 'V', 'X', 'L', 'C', 'D', 'M').
It is guaranteed that s is a valid roman numeral in the range [1, 3999].

Code

object Solution {
    def romanToInt(s: String): Int = {
        def toInt(ss:String, i:Char, v:Char, x:Char, num:Int):(Int, Int) = {
          val (a, b) = ss.span(_ == i)
          if(b.isEmpty) (a.length*num, a.length)
          else if(b.head == x) (num*9, 2)
          else if(b.head == v) (num*4, 2)
          else (a.length*num, a.length)
        }
        def toIntV(ss:String, i:Char, num:Int) = {
          if(ss.tail.takeWhile(_ == i).isEmpty) (num*5, 1) else (num*6, 2)
        }

        var index = 0
        var res = 0
        while(index < s.length) {
          val (n, inc) = s(index) match {
            case 'I' => toInt(s.drop(index), 'I', 'V', 'X', 1)
            case 'V' => toIntV(s, 'I', 1)
            case 'X' => toInt(s.drop(index), 'X', 'L', 'C', 10)
            case 'L' => toIntV(s, 'X', 10)
            case 'C' => toInt(s.drop(index), 'C', 'D', 'M', 100)
            case 'D' => toIntV(s, 'C', 100)
            case 'M' => toInt(s.drop(index), 'M', ' ', ' ', 1000)
          }
          res = res + n
          index = index + inc
        }
        res
    }
}

Results

Runtime: 516 ms, faster than 94.58% of Scala online submissions for Roman to Integer. Memory Usage: 53.1 MB, less than 89.16% of Scala online submissions for Roman to Integer.