day6_leetcode12

leetcode第12题:整数转罗马数字

1. 题目:
    

      

 

2. 题意分析:

给一个正整数,然后把它对应的每一个位上的数字用相应的罗马数字表示,要注意特殊的那几个的使用(4,9,40,90、、、、)。看到这个题我首先想到的就是以前遇到的一种题目,就是给买东西结账时,有多少种方法(可能表述的不清楚,不是用支付宝、微信什么的。而是假如要支付1元,而你手里的钱有1角,五角,一元的,但是数目不限,问有哪些组合方法)。所以这一次我也是用那个思路来做的。

 

3. 解法一:
代码:

class Solution:
    def intToRoman(self, num):
        num = str(num)
        num_list = []
        num_dict = {"1": "I", "5": "V", "10": "X", "50": "L", "100": "C", "500": "D", "1000": "M",
                    "4": "IV", "9": "IX", "40": "XL", "90": "XC", "400": "CD", "900": "CM"}
        for item in num:
            if len(num) != 0:
                row = "{0:0<{1}}".format(item, len(num))
                if row in num_dict:
                    num_list.append(num_dict[row])
                else:
                    n = "1"+row[1:]  # 例如row是"300", 则n就是100
                    count = int(row[0])  # 那么count就是3
                    if count > 5:
                        count_1 = 5*int(n)
                        count_2 = count-5
                        num_list.append("{0}".format(num_dict[str(count_1)]))
                        num_list.append(count_2*"{}".format(num_dict[n]))
                    else:
                        num_list.append(count*"{}".format(num_dict[str(n)]))
                num = num[1:]
        return "".join(num_list)


执行结果:

    
时间复杂度是O(n)=n
这儿有几个关键点。


(1)如何通过数字转化为罗马数字,我是选用字典的方法,先推出有哪些组合的方法,然后利用字典检索就可以将对应的罗马数字表示出来。


(2)例如给的数是738,那么我就可以先得到这样的组合(700+30+8),然后又细分得到这个组合(500+100+100+10+10+10+5+1+1+1),然后从字典中寻找出相应的罗马数字,组合成一个字符串就可以了。
接下来就是如何优化。

 

3.解法二:
代码:

class Solution:
    def intToRoman(self, num):
        num = str(num)
        romes = ""
        num_dict = {"1": "I", "5": "V", "10": "X", "50": "L", "100": "C", "500": "D", "1000": "M",
                    "4": "IV", "9": "IX", "40": "XL", "90": "XC", "400": "CD", "900": "CM"}
        for item in num:
            if len(num) != 0:
                row = "{0:0<{1}}".format(item, len(num))
                if row in num_dict:
                    romes += num_dict[row]
                    num = num[1:]
                    continue
                n = "1"+row[1:]  # 例如row是"300", 则n就是100, 如果row是3,那么n就是1
                count = int(row[0])  # 那么count就是3
                if count > 5:
                    count_1 = 5*int(n)  # 最高位用5代替,其余的以0代替,例如n=700,那么count_1=500
                    count_2 = count-5   # 获取n的最高位与5相减的值,例如,n=700,那么count_2=2
                    romes = romes + "{0}".format(num_dict[str(count_1)]) + count_2*"{}".format(num_dict[n])
                    num = num[1:]
                    continue
                romes += count*"{}".format(num_dict[str(n)])
                num = num[1:]
        return romes


执行结果:

    
时间复杂度还是O(n)=n


代码解释:
(1)这个代码和第一个变化不大,只是将不必要的条件判断语句进行了删改,对比执行结果,效果也不是很明显。

 

4. 最优解法:
我将已提交结果里的最优解复制了下来进行对比:

class Solution:
    def intToRoman(self, num):
        res = ''
        token = [(1000, 'M'), (900, 'CM'), (500, 'D'), (400, 'CD'), (100, 'C'), (90, 'XC'), (50, 'L'), (40, 'XL'), (10, 'X'), (9, 'IX'), (5, 'V'), (4, 'IV'), (1, 'I')]
        for n, t in token:
            while num >= n:
                res += t;
                num -= n
        return res

执行用时是116ms。而且人家这个代码量。。。。。

 

5.总结:
最近好像有点思维定式了,老是一看到整数就想着转化为字符串来处理,但是几次相同的经历表明,python处理数字比字符串、列表等要快的多。


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大骨熬汤

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值