LeetCode 12. Integer to Roman(整数转罗马数字)

原题:

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 an integer, convert it to a roman numeral. Input is guaranteed to be within the range from 1 to 3999.

罗马数字包含以下七种字符: I, V, X, L,C,D 和 M。

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

例如, 罗马数字 2 写做 II ,即为两个并列的 1。12 写做 XII ,即为 X + II 。 27 写做 XXVII, 即为 XX + V + II 。

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。数字 1 在数字 5 的左边,所表示的数等于大数 5 减小数 1 得到的数值 4 。同样地,数字 9 表示为 IX。这个特殊的规则只适用于以下六种情况:

  • I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。

  • X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。

  • C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。

给定一个整数,将其转为罗马数字。输入确保在 1 到 3999 的范围内。

Example 1:

Input: 3
Output: "III"

Example 2:

Input: 4
Output: "IV"

Example 3:

Input: 9
Output: "IX"

Example 4:

Input: 58
Output: "LVIII"

Explanation: C = 100, L = 50, XXX = 30 and III = 3.

Example 5:

Input: 1994
Output: "MCMXCIV"

Explanation: M = 1000, CM = 900, XC = 90 and IV = 4.

My solution

class Solution:
    def intToRoman(self, num):
        """
        采用从后向前的思路得到各位数分别进行转换
        :type num: int
        :rtype: str
        """
        if not 0 <= num <= 4000:
            print ('The input is out of the range 0 ~ 3999')
            return False
        digit = 0
        roman_num = ''
        while num:
            digit_num = num % 10
            num //= 10
            temp_roman = digit_num * (10**digit)    

            if digit == 0:
                if digit_num <= 3:                
                    roman_num += 'I'*digit_num
                elif digit_num == 4:      
                    roman_num += 'IV'
                elif digit_num == 5:      
                    roman_num += 'V'    
                elif 6 <= digit_num <= 8:
                    roman_num += 'V'
                    roman_num += 'I'*(digit_num - 5)
                elif digit_num == 9:      
                    roman_num += 'IX'
            elif digit == 1:
                if digit_num <= 3:                
                    roman_num = 'X'*digit_num + roman_num
                elif digit_num == 4:      
                    roman_num = 'XL' + roman_num
                elif digit_num == 5:      
                    roman_num = 'L'  + roman_num   
                elif 6 <= digit_num <= 8:
                    temp_digit_num = 'L'+ 'X'*(digit_num - 5)
                    roman_num = temp_digit_num + roman_num 
                elif digit_num == 9:      
                    roman_num = 'XC' + roman_num
            elif digit == 2:
                if digit_num <= 3:                
                    roman_num = 'C'*digit_num + roman_num
                elif digit_num == 4:      
                    roman_num = 'CD' + roman_num
                elif digit_num == 5:      
                    roman_num = 'D'  + roman_num  
                elif 6 <= digit_num <= 8:
                    temp_digit_num = 'D' + 'C'*(digit_num - 5)
                    roman_num = temp_digit_num + roman_num
                elif digit_num == 9:      
                    roman_num = 'CM' + roman_num
            elif digit == 3:
                if digit_num <= 3:                
                    roman_num = 'M'*digit_num + roman_num
                else:
                    print ('The input is out of the range 0 ~ 3999')
            else:
                print ('The input is out of the range 0 ~ 3999')

            digit += 1



        return roman_num         

上边代码并不难懂,效果一般!这里已经注意到几个特殊的值,可以根据这些值做文章。下边提供一种网上的代码思路:通过构建字典和列表,从高位到低位依次进行转换输出。因为小詹把注释写的很详细,这里就不做赘述了!

Reference solution

题目分析:一脸看去有点懵逼。还好示例给的比较有代表,简单来说就是要在字符串中找到符合要求的数字串!有符号,有范围限制。

越是题目长的题目越不能被吓到!知道了题目的意思,其实这题特别简单,没什么难点,就是列举出各个情况分类即可。注意str.isdigit()方法的应用即可。具体见下注释,小詹给了比较详细的注释,就不过多介绍了。

class Solution(object):
    def intToRoman(self, num):
        """
        :type num: int
        :rtype: str
        """
        #定义空字符串输出
        ans = ""
        #构建一个字典和一个列表;数字的匹配对应,列表用于输出添加到空字符串中输出
        values = {"M": 1000, "D": 500, "C": 100, "L": 50, "X": 10, "V": 5, "I": 1}
        literals = ["M", "D", "C", "L", "X", "V", "I"]
        #依次除以1000;100;10;1,进行处理
        for idx in [0, 2, 4]:
            #k表示整除得到的商,这里实际上只有在除以1000时会用的上(可以代个数试试)
            k = num // values[literals[idx]]
            #re表示取模后再除以低一个数量级得到的商
            re = (num % values[literals[idx]]) // values[literals[idx + 2]]
            #小詹提醒:输入在1-3999范围内,所以除以1000最大商为3
            ans += k * literals[idx]
            #这里针对不同的特殊情况分类处理
            #取模为9时
            if re >= 9:
                ans += literals[idx + 2] + literals[idx] 
            #取模为5;6;7;8时
            elif re >= 5:
                ans += literals[idx + 1] + (re - 5) * literals[idx + 2]
            #取模为4时
            elif re == 4:
                ans += literals[idx + 2] + literals[idx + 1]
            #取模为0;1;2;3时
            else:
                ans += re * literals[idx + 2]
            #取模后进行下一次循环
            num %= values[literals[idx + 2]]
        return ans

Note: 本章节自己需要注意反省的点有:
1. str与list互换
2. str 向后扩展就是 str += new_str;向前扩展就是str = new_str + str

猜你喜欢

转载自blog.csdn.net/Dby_freedom/article/details/82530335