前端算法(13)

103 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

罗马数字包含以下七种字符: I, V, X, LCD 和 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。 给定一个罗马数字,将其转换成整数。

输入: s = "III"
输出: 3

解题思路

思路一

我们先使用从左往右累加法,第一次仅记下左边第一位的值, 从第二次开始 每次用当前位的值跟上一位的值作比较,如果当前位置小于等于上个位置 直接累加,如果当前位置大于上个位置 需要加上当前位置与上个位置的差值 同时再减去上一次加的值 所以是当前 - 2*前位

var romanToInt = function(s) {
    let dict = {
        I: 1,
        V: 5,
        X: 10,
        L: 50,
        C: 100,
        D: 500,
        M: 1000
    }
    let result = 0
    for (var i = 0; i < s.length; i++) {
        let c = s[i]
        if (i == 0) {
            result = dict[c]
        } else {
            last_c = s[i-1]
            if (dict[last_c] >= dict[c]) {
                result += dict[c]
            } else {
                result += (dict[c] - 2 * dict[last_c])
            }
        } 
    }
    return result
};

思路二

先列出罗马数字集合,得出每个字符所代表的数字,在进行循环字符串 ,拿当前一位和下一位进行比较来决定是相加还是相减,当没有下一位时,做加法即可

var romanToInt = function(s) {
 var sum = 0
            var preNum = getValue(s.charAt(0))
            for(var i=1;i<s.length;i++){  
                var num = getValue(s.charAt(i))
                if(preNum<num){
                    sum-=preNum
                }else{
                    sum+=preNum
                }
                preNum=num;
            }
            sum+=preNum
            return sum;
};
function getValue(x){
    switch(x){
        case 'I':
        return 1;
        break;
        case 'V':
        return 5;
        break
        case 'X':
        return 10;
        break
        case 'L':
        return 50;
        break;
        case 'C':
        return 100;
        break;
        case 'D':
        return 500;
        case 'M':
        return 1000;
        break;
        default :
        return 0
    }
}

思路三

我们先将字符和整数建立成映射表,通常情况下只需将字符串分割成数组,然后利用 reduce 进行累加即可,通过观察我们发现,假如第 index 个字符串为特殊情况中的左值,且 index + 1 个字符串为特殊情况中的右值时,需要将总和减去第 index 个字符串对应的整数值

var romanToInt = function (s) {
    const mapping = {
        'I': 1,
        'V': 5,
        'X': 10,
        'L': 50,
        'C': 100,
        'D': 500,
        'M': 1000,
    }
    const hardCodeMapping = {
        "I": ["V", "X"],
        "X": ["L", "C"],
        "C": ["D", "M"]
    }
    const result = String(s).split('').reduce((preVal, currStr, index, arr) => {
        if (currStr in hardCodeMapping && index < arr.length - 1 && hardCodeMapping[currStr].includes(arr[
                index + 1])) {
            return preVal - mapping[currStr]
        }
        return preVal + mapping[currStr] 
    }, 0)
    return result
};