主页 > 其他  > 

12-罗马数字转整数

12-罗马数字转整数

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

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

方法一

要将罗马数字转换为整数,可以通过遍历罗马数字字符串,根据字符对应的数值以及罗马数字的规则来计算最终的整数结果。对于正常情况(小数字在大数字右边),直接累加对应数值;对于特殊情况(小数字在大数字左边),需要用大数字减去小数字。

function romanToInt(s: string): number { // 定义罗马数字字符与对应数值的映射 const romanMap: { [key: string]: number } = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000 }; let result = 0; for (let i = 0; i < s.length; i++) { // 获取当前字符对应的数值 const currentValue = romanMap[s[i]]; // 如果不是最后一个字符,并且当前字符对应的数值小于下一个字符对应的数值 if (i < s.length - 1 && currentValue < romanMap[s[i + 1]]) { // 表示是特殊情况,用下一个字符的数值减去当前字符的数值 result += romanMap[s[i + 1]] - currentValue; // 由于已经处理了当前字符和下一个字符,跳过下一个字符 i++; } else { // 正常情况,直接累加当前字符对应的数值 result += currentValue; } } return result; } // 示例调用 const romanNumeral = "MCMXCIV"; const integerValue = romanToInt(romanNumeral); console.log(`罗马数字 ${romanNumeral} 转换为整数是: ${integerValue}`); 代码解释 定义映射:创建一个对象 romanMap,将罗马数字字符映射到对应的整数值。初始化结果变量:result 用于存储最终转换得到的整数,初始化为 0。遍历罗马数字字符串: 对于每个字符,获取其对应的数值 currentValue。检查是否是特殊情况:如果当前字符不是字符串的最后一个字符,并且当前字符对应的数值小于下一个字符对应的数值,说明是特殊情况(如 IV、IX 等),此时用下一个字符的数值减去当前字符的数值,并累加到 result 中,同时跳过下一个字符(因为已经处理过了)。若不是特殊情况,直接将当前字符对应的数值累加到 result 中。 返回结果:遍历结束后,result 即为转换后的整数,将其返回。 复杂度分析 时间复杂度:O(n),其中  是罗马数字字符串的长度。因为只需要对字符串进行一次遍历。空间复杂度:O(1),只使用了常数级的额外空间,主要用于存储 romanMap 对象。  方法二  思路分析

可以先将特殊的组合(如 IV、IX 等)提前处理,把它们替换为一个特殊的单字符,并且给这个特殊字符赋予对应的数值。然后遍历处理后的字符串,将每个字符对应的数值累加起来,从而得到最终的整数结果。

代码实现 function romanToInt(s: string): number { // 定义特殊组合及其对应数值的映射 const specialMap: { [key: string]: [string, number] } = { "IV": ["#", 4], "IX": ["$", 9], "XL": ["%", 40], "XC": ["^", 90], "CD": ["&", 400], "CM": ["@", 900] }; // 替换特殊组合 for (const key in specialMap) { if (s.includes(key)) { const [replacement, value] = specialMap[key]; s = s.replace(key, replacement); } } // 定义单个罗马字符及其对应数值的映射 const romanMap: { [key: string]: number } = { "I": 1, "V": 5, "X": 10, "L": 50, "C": 100, "D": 500, "M": 1000, "#": 4, "$": 9, "%": 40, "^": 90, "&": 400, "@": 900 }; let result = 0; // 遍历处理后的字符串,累加每个字符对应的数值 for (const char of s) { result += romanMap[char]; } return result; } // 示例调用 const romanNumeral = "MCMXCIV"; const integerValue = romanToInt(romanNumeral); console.log(`罗马数字 ${romanNumeral} 转换为整数是: ${integerValue}`); 代码解释 特殊组合映射:创建 specialMap 对象,将特殊的罗马数字组合(如 IV、IX 等)映射为一个特殊字符和对应的数值。例如,IV 映射为 ["#", 4],表示用 # 替换 IV,且其代表的数值是 4。替换特殊组合:遍历 specialMap,如果罗马数字字符串 s 中包含某个特殊组合,就用对应的特殊字符进行替换。单个字符映射:创建 romanMap 对象,将单个罗马字符(包括替换后的特殊字符)映射到对应的整数值。遍历累加:遍历处理后的字符串 s,将每个字符对应的数值累加到 result 中。返回结果:最终返回 result,即转换后的整数。 复杂度分析 时间复杂度:O(n),其中  是罗马数字字符串的长度。虽然有替换特殊组合的操作,但由于特殊组合的数量是固定的(6 种),替换操作的时间复杂度可以看作常数。主要的时间开销在于遍历处理后的字符串,所以整体时间复杂度为 。空间复杂度:O(1),使用的额外空间主要是存储映射关系的对象,这些对象的大小是固定的,不随输入字符串长度的增加而增加,因此空间复杂度为常数级。

这种方法的优势在于代码逻辑相对清晰,将特殊组合的处理和单个字符的处理分开,便于理解和扩展。如果后续需要添加更多的特殊规则,只需要修改 specialMap 和 romanMap 即可。

其他解法 基于反向遍历的解法

前面的方法多是正向遍历,其实反向遍历罗马数字字符串也能解决问题。反向遍历时,若当前字符对应的数值不小于前一个已处理字符对应的数值,就累加该数值;若小于,则减去该数值。

function romanToInt(s: string): number { const romanMap: { [key: string]: number } = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000 }; let result = 0; let prevValue = 0; // 从字符串末尾开始反向遍历 for (let i = s.length - 1; i >= 0; i--) { const currentValue = romanMap[s[i]]; if (currentValue >= prevValue) { result += currentValue; } else { result -= currentValue; } prevValue = currentValue; } return result; } 复杂度分析 时间复杂度:O(n),这里的  是字符串 s 的长度,因为只对字符串进行了一次反向遍历。空间复杂度:O(1),只使用了常数级的额外变量来存储数值和结果。 递归解法

递归也是一种可行的思路,把罗马数字字符串的转换问题分解成子问题。如果字符串长度为 1,直接返回对应字符的数值;如果字符串长度大于 1,先判断前两个字符是否构成特殊组合,若是则处理该组合并递归处理剩余部分,若不是则处理第一个字符并递归处理剩余部分。

function romanToInt(s: string): number { const romanMap: { [key: string]: number } = { 'I': 1, 'V': 5, 'X': 10, 'L': 50, 'C': 100, 'D': 500, 'M': 1000, 'IV': 4, 'IX': 9, 'XL': 40, 'XC': 90, 'CD': 400, 'CM': 900 }; if (s.length === 0) { return 0; } if (s.length === 1) { return romanMap[s]; } const twoChar = s.slice(0, 2); if (romanMap[twoChar]) { return romanMap[twoChar] + romanToInt(s.slice(2)); } else { return romanMap[s[0]] + romanToInt(s.slice(1)); } } 复杂度分析 时间复杂度:O(n),因为每次递归调用都会处理一个或两个字符,最终遍历完整个字符串。空间复杂度:O(n),递归调用栈的深度最大为 ,其中  是字符串的长度。 基于规则匹配表的解法

构建一个规则匹配表,将罗马数字的字符组合及其对应的数值列出来,然后在遍历字符串时,根据规则匹配表来确定数值。

function romanToInt(s: string): number { const rules: [string, number][] = [ ['M', 1000], ['CM', 900], ['D', 500], ['CD', 400], ['C', 100], ['XC', 90], ['L', 50], ['XL', 40], ['X', 10], ['IX', 9], ['V', 5], ['IV', 4], ['I', 1] ]; let result = 0; let index = 0; while (index < s.length) { for (const [roman, value] of rules) { if (s.startsWith(roman, index)) { result += value; index += roman.length; break; } } } return result; } 复杂度分析 时间复杂度:O(n),其中  是字符串的长度。虽然有嵌套循环,但内层循环的规则数量是固定的,整体上每个字符最多被处理一次。空间复杂度:O(1),规则匹配表的大小是固定的,不随输入字符串长度的变化而变化。

 

标签:

12-罗马数字转整数由讯客互联其他栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“12-罗马数字转整数