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處理數字比字符串、列表等要快的多。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章