Leetcode No.13-罗马数字转整数(简单)——Java/Python

难度:简单
罗马字符与数字的对应表.png

通常情况下,罗马数字中小的数字在大的数字的右边。但也存在特例,例如 4 不写做 IIII,而是 IV。这个特殊的规则只适用于以下六种情况:
I 可以放在 V (5) 和 X (10) 的左边,来表示 4 和 9。
X 可以放在 L (50) 和 C (100) 的左边,来表示 40 和 90。
C 可以放在 D (500) 和 M (1000) 的左边,来表示 400 和 900。
给定一个罗马数字,将其转换成整数。输入确保在 1 到 3999 的范围内。

此题的难点在于如何去处理以上特殊的规则。

方法一:(遍历法)

也是我们最容易想到方法,看到这种类似于列表一一对应的问题,第一想法就是用switch…case…去把罗马字母和数值对应起来,然后再用if语句去处理特殊的情况。

  1. 定义一个获取罗马字符对应数字的静态方法getValue(char c),使用switch来获取字符对应的数字。
  2. 遍历从第一个字符开始,比较当前字符与后一个字符对应数字大小,大于等于则加上当前字符所对应的数值,否则减。最后一个字符也同样是加。
知识盲点:
  • charAt函数

    charAt(int index)方法是一个能够用来检索特定索引下的字符实例的方法。

    charAt()方法返回指定索引位置char值。索引范围为0~length()-1,如: str.charAt(0)检索str中的第一个字符,str.charAt(str.length()-1)检索最后一个字符。

    Java实例:

    public class Test {
        public static void main(String[] args) {
            String s = "123456";
            for(int index=0;index<s.length();index++)//将字符串中的字符逐个按行输出
            {
                System.out.print(s.charAt(index));
            }
        }
    }
    
下面贴出该方法的解题代码:
class Solution {
    public static int getValue(char c){
        switch(c){
            case 'I':
                return 1;
            case 'V':
                return 5;
            case 'X':
                return 10;
            case 'L':
                return 50;
            case 'C':
                return 100;
            case 'D':
                return 500;
            case 'M':
                return 1000;
            default:
                throw new IllegalArgumentException("Illegal character");
        }
    }

    public int romanToInt(String s) {
        int len = s.length();
        int num = 0;
        for(int i=0;i<len;i++){
            if(i==len-1 || getValue(s.charAt(i)) >= getValue(s.charAt(i+1)))
                num += getValue(s.charAt(i));
            else
                num -= getValue(s.charAt(i));
        }                 
        return num;
    }
}
遇到的问题:
  • 在写default的时候没有使用了syso输出了一个语句,但该函数的返回值类型为int而不是void,于是改成了throw函数抛出异常。

  • 在比较前一项与后一项的数值的时候,没有考虑循环范围是0-length-1,直接就比位置i与位置i+1的大小,但是i+1会越界,于是将最后一位单独拎出来计算,if条件里两项判断,或连接。

方法二:(Hash表,字母组合求解法)

  • 首先将所有的组合可能性列出并添加到哈希表中
  • 然后对字符串进行遍历,由于组合只有两种,一种是1个字符,一种是2个字符,其中2个字符优先于1个字符
  • 先判断两个字符的组合在哈希表中是否存在,存在则将值取出加到结果 ans 中,并向后移2个字符。不存在则将判断当前1个字符是否存在,存在则将值取出加到结果ans中,并向后移1个字符
  • 遍历结束返回结果 ans
回顾:
  • map.containsKey(Object key):判断Map集合对象中是否包含指定的键名
  • map.get(Object key):输入键名,返回键值(这里的键名是字母组合,键值是对应数字)
下面贴出该方法的解题代码:
class Solution {
    public int romanToInt(String s) {
        Map<String, Integer> map = new HashMap<>();
        map.put("I", 1);
        map.put("IV", 4);
        map.put("V", 5);
        map.put("IX", 9);
        map.put("X", 10);
        map.put("XL", 40);
        map.put("L", 50);
        map.put("XC", 90);
        map.put("C", 100);
        map.put("CD", 400);
        map.put("D", 500);
        map.put("CM", 900);
        map.put("M", 1000);
        
        int ans = 0;
        for(int i = 0;i < s.length();) {
        	//先进行2字符判断
            if(i + 1 < s.length() && map.containsKey(s.substring(i, i+2))) {
                ans += map.get(s.substring(i, i+2));
                i += 2;
            }
            //不是2字符情况再加1字符对应值 
            else {
                ans += map.get(s.substring(i, i+1));
                i ++;
            }
        }
        return ans;
    }
}
作者:guanpengchn
链接:https://leetcode-cn.com/problems/roman-to-integer/solution/hua-jie-suan-fa-13-luo-ma-shu-zi-zhuan-zheng-shu-b/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

通过此题我还发现,hashmap比switch慢一倍……

再用神奇的Python写一下吧,思路还是以上思路。

class Solution:
    def romanToInt(self, s: str) -> int:
        mapping = {'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}
        result = 0
        for i in range(len(s)-1):
            if mapping[s[i]] < mapping[s[i + 1]]:
                result -= mapping[s[i]]
            else:
                result += mapping[s[i]]
                
		return result+mapping[s[-1]]
        #众所周知,s[-1]表示最后一个字符,相当于s[len(s)-1]     

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值