题目描述#

罗马数字包含以下七种字符:IVXLCDM

字符 数值
I 1
V 5
X 10
L 50
C 100
D 500
M 1000

例如:

  • II 表示 2
  • XII 表示 12
  • XXVII 表示 27

通常情况下,罗马数字中小的数字写在大的数字右边,表示相加。但也存在特殊情况:

  • I 可以放在 VX 左边,表示 4 和 9
  • X 可以放在 LC 左边,表示 40 和 90
  • C 可以放在 DM 左边,表示 400 和 900

给定一个罗马数字字符串,将其转换成对应的整数。

知识边界#

这道题的核心是字符到数值的映射以及相邻字符大小关系的判断

1. 哈希表映射#

题目中每个罗马字符都对应一个固定整数,因此很适合用哈希表存储映射关系。

Go 中可以使用 map[byte]int

var Roman = map[byte]int{
	'I': 1,
	'V': 5,
	'X': 10,
	'L': 50,
	'C': 100,
	'D': 500,
	'M': 1000,
}

这里使用 byte 而不是 string,因为字符串中的每个罗马字符都是单个 ASCII 字符,转成字节后访问更直接,效率也更高。

2. 字符串转字节切片#

Go 中字符串可以转成 []byte

s := []byte(ss)

这样就可以通过下标访问每一个字符:

x := s[i]
y := s[i+1]

3. 贪心判断相邻关系#

对于当前字符 s[i]

  • 如果它小于右边字符 s[i+1],说明它属于减法组合,应当减去
  • 否则它应当加上

例如 IV

  • I < V,所以先减去 1
  • 最后再加上 5
  • 结果为 4

4. Go 中的切片遍历#

代码里使用了:

for i, _ := range s[:len(s)-1]

含义是遍历到倒数第二个字符,因为循环体内会访问 s[i+1],如果遍历到最后一个字符就会越界。

这是一种很常见的写法,用来处理“当前元素和下一个元素比较”的问题。

5. 常见错误点#

越界访问#

如果直接遍历整个字符串,再访问 s[i+1],最后一次会发生下标越界。

最后一个字符漏算#

因为循环只遍历到倒数第二个字符,所以最后一个字符需要单独加上:

return ans + Roman[s[len(s)-1]]

使用 string 逐个比较#

虽然也能做,但本题字符都是单字节,使用 byte 更自然,代码更简洁。

思路#

把罗马数字字符串转成字节切片后,从左到右遍历,比较当前字符和下一个字符的大小关系。

如果当前值小于后一个值,说明当前字符是减法部分,应该从答案中减去;否则说明当前字符是正常加法部分,应该加到答案中。最后循环没有处理最后一个字符,所以再单独补上最后一个字符的值。

思路一#

先建立罗马字符到整数的映射表,然后遍历字符串中除最后一个字符外的所有位置。

设当前字符为 x,下一个字符为 y

  • Roman[x] < Roman[y],则 ans -= Roman[x]
  • 否则 ans += Roman[x]

最后返回:

ans + Roman[s[len(s)-1]]

为什么这样做是正确的:

对于罗马数字,只有当一个较小数字出现在较大数字左边时,它才表示减法。题目也明确说明了这种规则只会出现在合法的六种情况中。因此,只需要比较当前字符和后一个字符:

  • 小于后一个字符,就应减去当前值
  • 否则就应加上当前值

这样每个字符都会被正确处理一次,最后一个字符没有右邻居,必然直接加上即可。

时间复杂度为 O(n),其中 n 是字符串长度,因为只遍历一遍字符串。

空间复杂度为 O(1)。映射表大小固定,额外变量数量也固定。虽然把字符串转成了字节切片,但这一部分按常见题解写法处理,整体辅助开销与输入长度线性相关;若只看除输入外的算法额外结构,核心思路仍然是常数级。

代码#

var Roman = map[byte]int{
	'I': 1,
	'V': 5,
	'X': 10,
	'L': 50,
	'C': 100,
	'D': 500,
	'M': 1000,
}

func romanToInt(ss string) int {
	ans := 0
	s := []byte(ss)
	for i, _ := range s[:len(s)-1] {
		x, y := s[i], s[i+1]
		if Roman[x] < Roman[y] {
			ans -= Roman[x]
		} else {
			ans += Roman[x]
		}
	}
	return ans + Roman[s[len(s)-1]]
}
本站总访问量  ·  访客数
你的IP 获取中…