【每日算法】力扣13. 罗马数字转整数

175 阅读4分钟

「这是我参与2022首次更文挑战的第22天,活动详情查看:2022首次更文挑战」。

描述

罗马数字包含以下七种字符: 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 。

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

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

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

给定一个罗马数字,将其转换成整数。

 

示例 1:

输入: s = "IX"
输出: 9
示例 2:

输入: s = "LVIII"
输出: 58
解释: L = 50, V= 5, III = 3.
示例 3:

输入: s = "MCMXCIV"
输出: 1994
解释: M = 1000, CM = 900, XC = 90, IV = 4.

提示:

1 <= s.length <= 15

s 仅含字符 ('I', 'V', 'X', 'L', 'C', 'D', 'M')

题目数据保证 s 是一个有效的罗马数字,且表示整数在范围 [1, 3999] 内

题目所给测试用例皆符合罗马数字书写规则,不会出现跨位等情况。

IL 和 IM 这样的例子并不符合题目要求,49 应该写作 XLIX,999 应该写作 CMXCIX 。

做题

这学习成本也太大了吧,还要先学习一下罗马数字,才能做这道算法,这还是简单题吗?

image.png

看了一会,我们需要知道的东西如下:

  1. 罗马数字是右加左減的。当数值比较小的字符遇到数值比较大的字符,就用大的减小的,就得到了这两个字符表达的数值;当数值比较大的字符遇到数值比较小的字符,就相加。更加简单一点地说,一个字符遇到数值比较大的字符,就会变成负数。
  2. 罗马数字只有这几个字符:I(1)、V(5)、X(10)、L(50)、C(100)、D(500)和M(1000)。

因为我们只需要会读罗马数字就好了,不需要考虑如何构建一个罗马数字,所以题目种提到的很多特殊的、不符合题目要求的罗马数字我们也不用管,只要会读就行。

拿例题来模拟一下读数的过程, s = "MCMXCIV"(1994)

我们在遍历字符串的时候是从左往右的,这里我们也要按照从左往右的顺序。

M(1000)C(100)M(1000)X(10)C(100)I(1)V(5)

sum = 0;

sum += M(1000);

因为 C(100) 遇到了 M(1000),所以 C(-100)。

sum += C(-100);

sum += M(1000);

因为 X(10) 遇到了 C(100),所以 X(-10)。

sum += X(-10);

因为 I(1) 遇到了 V(5) ,所以 I(-1)。

sum += I(-1);

sum += V(5);

所以我们每次循环,都要拿到下一位的字符,用下一个字符的值比较判断现在的值的正负。

至于字符与数值的映射,莫得办法,要通过一个哈希表来转换,switch也行。

class Solution {
    public int romanToInt(String s) {
        int sum = 0;
        int length = s.length();
        for(int i = 0; i<length ;i++ ){
            int currentValue = trans(s.charAt(i));
            //int nextValue = trans(s.charAt(i+1));这里不能直接转换下一个字符,因为当处理最后一个字符时,没有下一个字符
            if( i < length-1 && currentValue < trans(s.charAt(i+1))){
                //当前字符小于下一个字符,变成负数
                sum-=currentValue;
            }else{
                //最后一个字符也是直接相加
                sum+=currentValue;
            }
        }
        return sum;
    }

    private int trans(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;
        }
        return 0;
    }
}

image.png

最后

今天就到这里了。

这里是程序员徐小白,【每日算法】是我新开的一个专栏,在这里主要记录我学习算法的日常,也希望我能够坚持每日学习算法,不知道这样的文章风格您是否喜欢,不要吝啬您免费的赞,您的点赞、收藏以及评论都是我下班后坚持更文的动力。