[LeetCode] Roman_To_Integer_20190116

题目:

Leetcode等级easy

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, two is written as II in Roman numeral, just two one’s added together. Twelve is written as, XII, which is simply X + II. The number twenty seven 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. Input is guaranteed to be within the range from 1 to 3999.

Example 1:
Input: "III"
Output: 3

Example 2:
Input: "IV"
Output: 4

Example 3:
Input: "IX"
Output: 9

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

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

分析及思路:

首先对题目做分析如下:

总的来说,罗马数字不外乎这几种组合方式:第一种是几个相同的组合如III,II分别代表32,第二种是较小数在较大数右侧组合如VI, XII分别代表612,第三种是较小数在左侧的组合如IV,IX分别代表49,还有一种是单个判断,一个符号代表一个数。

如果我们统一按照从左到右的方式计算总和,那么在这四种组合方式中,第一种、第二种都是可以通过最后一种方法计算得到的,单个获取值相加即可。也就是说只需要考虑两种情况:一种是单个符号的情况,一种是较小数在左侧的情况。

接下来便是选择实现方法了,好的方法可以节省代码量,并具有更高的速度:

自己对字符串操作比较熟悉,而且字符串处理也很快,所以类似的题目,第一想法就是用字符串方法实现。一开始是想构建一堆if-elif-else,只需要把每种情况囊括进去就ok,写了一半感觉太乱了,于是选用字符串函数直接替换符合条件的值,最后统一为列表依次取值计算。

还有一种方法,既然这里面有映射关系,那哈希就应该被想到,python中有现成的数据结构:字典,从这个角度也是有一种方法能解的,速度应该更加快。

代码:

利用字符串函数和列表实现:

class Solution:
    def romanToInt(self, x):
        """
        :type x: str
        :rtype: int
        """
        res = 0

        # 2位不同
        x = x.replace('IV', '4,')
        x = x.replace('IX', '9,')
        x = x.replace('XL', '40,')
        x = x.replace('XC', '90,')
        x = x.replace('CD', '400,')
        x = x.replace('CM', '900,')

        # 1位
        x = x.replace('I', '1,')
        x = x.replace('V', '5,')
        x = x.replace('X', '10,')
        x = x.replace('L', '50,')
        x = x.replace('C', '100,')
        x = x.replace('D', '500,')
        x = x.replace('M', '1000,')

        l = x.rstrip(',').split(',')
        for each in l:
            res += int(each)
        return res

利用字典实现:

class Solution:
    def romanToInt(self, x):
        """
        :type x: str
        :rtype: int
        """
        i = 0
        res = 0
        one_dict = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
        two_dict = {'IV':4, 'IX':9, 'XL':40, 'XC':90, 'CD':400, 'CM':900}

        while i<len(x):
            if x[i:i+2] in two_dict:
                res += two_dict[x[i:i+2]]
                i += 2
            else:
                res += one_dict[x[i]]
                i += 1
        return res

总结:

由于运行耗时感觉误差太大了,没什么意义,就不再贴图了,以实际运行时为准。

这个题目用hash的方式感觉是更好的,不过无论是哪种方法,总体思路的核心是一个映射关系,只要分析清楚映射关系,代码是比较好构思的,而且速度也不会相差太大。

猜你喜欢

转载自blog.csdn.net/zhengyajun_email/article/details/86504615