leetCode 编号13和12

79 阅读5分钟

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

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

思路:
  1. 一个字符对应一个数字 考虑使用哈希键值对比的形式,所以将所有值包括特殊IV之类的,生成哈希表
  2. 特殊情况是存在2个字符串的解析,而且是前的为减,其他为正常键值对相加即可,所以考虑使用快慢指针的形式,而且是从后往前遍历(因为特殊情况是在前为减)
  3. 正常遍历,对比相应哈希表结果相加,为特殊IV之类时,从当前索引值前2位开始新的循环
/**
 * @param {string} s
 * @return {number}
 */
var romanToInt = function (s) {
    // 所有可能出现的罗马数字的组合哈希表
    let obj = {
        'IV': 4,
        'IX': 9,
        'XL': 40,
        'XC': 90,
        'CD': 400,
        'CM': 900,
        'I': 1,
        'V': 5,
        'X': 10,
        'L': 50,
        'C': 100,
        'D': 500,
        'M': 1000
    }
    let len = s.length
    let result = 0
    // 从后往前遍历
    for (var a = len - 1; a > -1; a--) {
        // 题目描述中有意义的罗马值最多为2个字符串组成
        // 快慢指针 组合成新的字符串
        let b = a - 1
        let newValue = s[b] + s[a]
        // 如果newValue组成的字符串在对象obj中有值 说明为特殊的4、9之类的值 下一次循环从a往前移两位索引开始
        if (a > 0 && obj[newValue]) {
            result = result + obj[newValue]
            a--
        } else {
            result = result + obj[s[a]]
        }
    }
    return result
};

12. 整数转罗马数字:七个不同的符号代表罗马数字,其值如下:

符号
I1
V5
X10
L50
C100
D500
M1000

罗马数字是通过添加从最高到最低的小数位值的转换而形成的。将小数位值转换为罗马数字有以下规则:

  • 如果该值不是以 4 或 9 开头,请选择可以从输入中减去的最大值的符号,将该符号附加到结果,减去其值,然后将其余部分转换为罗马数字。
  • 如果该值以 4 或 9 开头,使用 减法形式,表示从以下符号中减去一个符号,例如 4 是 5 (V) 减 1 (I): IV ,9 是 10 (X) 减 1 (I):IX。仅使用以下减法形式:4 (IV),9 (IX),40 (XL),90 (XC),400 (CD) 和 900 (CM)。
  • 只有 10 的次方(IXCM)最多可以连续附加 3 次以代表 10 的倍数。你不能多次附加 5 (V),50 (L) 或 500 (D)。如果需要将符号附加4次,请使用 减法形式

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

思路:
  1. 生成数字与罗马数字的哈希表
  2. 将数字拆分为各个单位(个、十、百、千)下的值
  3. 遍历将各个位置生成对应的罗马数字,其中的难点是5是一个分界点,因为有各个单位下的5的对应罗马数字,所以要对5进行求余,求余后的整数、余数部分的罗马数字相加,则为对应的罗马数字的值
  4. 重新拼接罗马数字的数组
/**
 * @param {number} num
 * @return {string}
 */
var intToRoman = function(num) {
    // 数字和罗马数字的键值对
     let obj = {
        4: 'IV',
        9: 'IX',
        40: 'XL',
        90: 'XC',
        400: 'CD',
        900: 'CM',
        1: 'I',
        5: 'V',
        10: 'X',
        50: 'L',
        100: 'C',
        500: 'D',
        1000: 'M'
    }
    // 数字拆分成字符串数组 方便后续生成相应的个、十、百、千
    let newArr = num.toString().split('')
    let len = newArr.length - 1
    // 每一个数字遍历生成新的罗马数字数组
    let numArr = newArr.map((item, index) => {
        // 根据相应的索引对应幂生成对应的单位(个、十、百、千)
        let unitValue = Math.pow(10, (len - index))
        // 如果直接存在 则直接获取相应键值对值
        if(obj[item*unitValue]) {
            return obj[item*unitValue]
        }
        // 哈希表内不存在 说明是2、3、6、7、8内的数字
        // 根据是否 > 5判断整数部分是否有值
        // 取对应的5开头的整数的罗马数字
        let integerStr = item > 5 ? obj[5*unitValue] : ''
        // 除5求余
        let remainder = item % 5
        let remainderStr = ''
        // 对应的1、10、100、1000的单位值
        let unitStr = obj[unitValue]
        // 根据余数循环相加 单位值
        for(let i = 0; i < remainder; i++) {
            remainderStr = remainderStr + unitStr
        }
        // 整数值 + 余数值 == 罗马数字值
        return integerStr + remainderStr
    })
    let result = ''
    // 将所有的罗马数字的数组拼接为字符串
    numArr.forEach(item => result = result + item)
    return result
};
方法二

这个方法是我看到其他人的题解的,我觉得比我自己的好就转载一下,点此跳转至题解具体位置

思路
  1. 第一步还是生成相应的值的集合
  2. 还是拆分,从最大值开始按相应单位值(1000、100、10、1)生成罗马数字,每生成一个减去相应的单位的值
  3. 并不担心5的分界点因为5的时候,会匹配到相应的D、L、V字段,然后再通过num-=intArr[index]减去了相应的值
var intToRoman = function(num) {
    let intArr=[1000,900,500,400,100,90,50,40,10,9,5,4,1];
    let RomanArr=["M", "CM", "D", "CD", "C", "XC", "L", "XL", "X", "IX", "V", "IV", "I"];
    let index=0;
    let res="";
    while(index<13){
        while(num>=intArr[index]){
            res+=RomanArr[index];
            num-=intArr[index];
        }
        index++;
    }
    return res
};

作者:不吃辣