Python刷LeetCode之题目#13罗马数字转整数

博客探讨了如何使用Python解决LeetCode上的罗马数字转整数问题,通过两种不同的实现方式,包括直接匹配和利用字典优化。作者强调了代码优化和模式识别的重要性,并分享了一种更优的解决方案,该方案利用了罗马数字中特定组合的规律。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python刷LeetCode之题目#13罗马数字转整数


题目描述

题目的描述如下图所示,其链接见:罗马数字转整数

图片1
在这里插入图片描述

题目理解

我是按照从左往右读罗马数字的,发现一般的罗马数字,一个就代表一位,但是有特殊的六种两个字母组合,必须组合起来读。这些内容就是我第一次分析出来的模式(有点pattern recognition的感觉在里面)。
所以第一次写的算法就是从左往右读,读了1位就踢掉这1位,读了2位就踢掉2位,把相应的数值加起来,判断剩下的字符串是否为空,如果为空就结束,不空就继续。

我的代码

class Solution:
    def romanToInt(self, s: str) -> int:
        n = 0
        while(s!=''):
            if len(s) == 1:
                if s == 'I':
                    n += 1
                elif s == 'V':
                    n += 5
                elif s == 'X':
                    n += 10
                elif s == 'L':
                    n += 50
                elif s == 'C':
                    n += 100
                elif s == 'D':
                    n += 500
                else:
                    n += 1000
                s = s[1:]
            else:
                if s[0:2] == 'IV':
                    n += 4
                    s = s[2:]
                elif s[0:2] == 'IX':
                    n += 9
                    s = s[2:]
                elif s[0:2] == 'XL':
                    n += 40
                    s = s[2:]
                elif s[0:2] == 'XC':
                    n += 90
                    s = s[2:]
                elif s[0:2] == 'CD':
                    n += 400
                    s = s[2:]
                elif s[0:2] == 'CM':
                    n += 900
                    s = s[2:]
                else:
                    if s[0] == 'I':
                        n += 1
                    elif s[0] == 'V':
                        n += 5
                    elif s[0] == 'X':
                        n += 10
                    elif s[0] == 'L':
                        n += 50
                    elif s[0] == 'C':
                        n += 100
                    elif s[0] == 'D':
                        n += 500
                    elif s[0] == 'M':
                        n += 1000
                    s = s[1:]        
        return n 

可以看到整个代码非常的冗长,大眼一扫,就知道肯定不怎么滴,所以也就不怎么细说了。

所以,我又接着想了第二种实现过程,如果利用字典,把这些罗马字母对应的数值以键值对的方式存储在字典里,这样每次调用就很方便了。所以我的这个第二个代码就很简洁明了:判断当前字符串是否为空,不为空时,直接判断它的前两位,即s[0:2]是否在字典中,这里有一个小技巧,就是不用再判断它的长度是否有两位以上,如果长度不足两位,它自然就被分到else里了。然后就是利用字符串的切片操作,踢掉已经考虑过的字母,接着进入下一次循环中。

class Solution:
    def romanToInt(self, s: str) -> int:
        n = 0
        re = dict()
        re['I'] = 1
        re['V'] = 5
        re['X'] = 10
        re['L'] = 50
        re['C'] = 100
        re['D'] = 500
        re['M'] = 1000
        re['IV'] = 4
        re['IX'] = 9
        re['XL'] = 40
        re['XC'] = 90
        re['CD'] = 400
        re['CM'] = 900
        # re = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000, 'IV':4, 
        # 'IX':9, 'XL':40, 'XC':90, 'CD':400, 'CM':900}
        while(s!=''):
            if s[0:2] in re:
                n += re[s[0:2]]
                s = s[2:]
            else:
                n += re[s[0]]
                s = s[1:]
        return n

这一次代码的运行结果就很好,结果如下图:
在这里插入图片描述
啊哈哈哈哈~~~,这个结果比它的官方代码的结果还要好,所以在这里就不说它的做法了。

另外,我在讨论区,看到了一种解法,我觉得特别好,是我所没有想到的,所以在这里也说一下。就是,罗马数字字母排列的模式里,特别的六种组合,都是小数字排在了大数字的左边,但是正常情况下,都是左边的字母所代表的数字更大。这是一个非常特殊的模式,正好可以利用这个模式来进行判断,如果当前位比右边一位更大,那么当前位直接读就好了;如果当前位比右边位要小,那么说明他俩是一个组合,对于这个组合,当前位的读取是要做减法;然后循环至下一位。
以上算法可由LeetCode用户pony Ma的代码实现如下:

class Solution(object):
    def romanToInt(self, s):
        """
        :type s: str
        :rtype: int
        """
        dct = {'M':1000,'D':500,'C':100,'L':50,'X':10,'V':5,'I':1}
        i,res = 0,0
        while i < len(s)-1:
            if dct[s[i]] < dct[s[i+1]]:
                res -= dct[s[i]]
            else:
                res += dct[s[i]]
            i += 1
        return res+dct[s[-1]]

总结

尽可能多的挖掘出计算流程,数据本身所具有的某种模式和特点,挖掘的越多,并把这些模式和特点利用起来,当然,再结合一些特定的数据结构,就会编写出越来越棒的算法程序了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值