)
LeetCode-Go 题解精讲13. Roman to Integer 罗马数字转整数Go 实现【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go导读本文以 LeetCode 第 13 题Roman to Integer罗马数字转整数为核心完整讲解题目规则、六类减法特例并逐行剖析 LeetCode-Go 仓库中romanToInt的 Go 实现与配套测试。读完本文你将掌握罗马数字「大数在前为加、小数在前为减」的解析规律理解单次线性扫描即可完成转换的算法思路并能直接运行本仓库的测试用例验证正确性。一、题目描述罗马数字由以下七种不同符号表示符号 Symbol数值 ValueI1V5X10L50C100D500M1000例如数字 2 写作II即两个 1 相加12 写作XII即X II27 写作XXVII即XX V II。罗马数字通常按照从大到小、从左到右书写。但数字 4 并不写作IIII而是写作IV——因为 1 在 5 的前面表示用 5 减去 1 得到 4。同理数字 9 写作IX。这种「减法」规则只适用于以下六种情况I可以放在V5和X10左边表示 4 和 9X可以放在L50和C100左边表示 40 和 90C可以放在D500和M1000左边表示 400 和 900。题目要求给定一个罗马数字将其转换成整数。输入保证在 1 到 3999 的范围内。二、官方示例示例输入输出说明示例 1III3三个 1 相加示例 2IV41 在 5 前做减法示例 3IX91 在 10 前做减法示例 4LVIII58L 50, V 5, III 3示例 5MCMXCIV1994M 1000, CM 900, XC 90, IV 4以示例 5 的MCMXCIV为例它可拆解为M CM XC IV即1000 900 90 4 1994正是减法规则与加法规则混合使用的典型场景。三、解题思路本题属于简单题按照题目给出的罗马数字字符数值逐位计算出对应的十进制数即可。关键观察是「小数在左」意味着减法「小数在右」意味着加法。因此有两种经典解法从左到右扫描比较当前字符与下一字符的数值若当前值小于下一值则减去当前值否则加上当前值从右到左扫描本仓库采用维护一个lastint记录「右边相邻字符」的数值若当前字符数值小于右边字符数值说明出现了减法组合做减法否则做加法。从右到左扫描的优势是只需一次遍历即可完成全部处理时间复杂度 O(n)空间复杂度 O(1)n 为字符串长度题目限制 n 最大对应 3999即最多约 15 个字符。四、Go 实现逐行剖析LeetCode-Go 仓库中该题的实现位于 leetcode/0013.Roman-to-Integer/13. Roman to Integer.go完整代码如下package leetcode var roman map[string]int{ I: 1, V: 5, X: 10, L: 50, C: 100, D: 500, M: 1000, } func romanToInt(s string) int { if s { return 0 } num, lastint, total : 0, 0, 0 for i : 0; i len(s); i { char : s[len(s)-(i1) : len(s)-i] num roman[char] if num lastint { total total - num } else { total total num } lastint num } return total }4.1 符号表roman代码通过包级变量roman建立「字符 → 数值」的映射表与题目给出的七种符号一一对应。这种 map 查表方式可读性强、扩展方便是处理有限字符集映射的常用做法。4.2 空串防护if s { return 0 }对空字符串直接返回 0避免后续切片操作越界。这一点也在仓库测试用例中得到了覆盖见下文测试章节。4.3 从右向左的减法判定num, lastint, total : 0, 0, 0 for i : 0; i len(s); i { char : s[len(s)-(i1) : len(s)-i] num roman[char] if num lastint { total total - num } else { total total num } lastint num }核心逻辑分四步反向取字符s[len(s)-(i1) : len(s)-i]从字符串末尾向开头逐个截取单字符用切片而非char字节是为了直接作为 map 的 string 键查表取值num roman[char]得到当前字符数值比较并累加若num lastint说明当前字符在它右边较大数字的左边构成减法组合如IV、IX、XC、CM从总数中减去num否则直接加上num更新lastint记录已处理的右边字符数值供下一次迭代比较。4.3.1 以IV为例推演反向取到Vnum 5lastint 05 0total 5lastint 5反向取到Inum 11 5判定为减法total 5 - 1 4。最终返回 4与题目示例一致。4.3.2 以MCMXCIV为例推演从右往左依次处理V → I → C → X → M → C → M处理字符numlastint右边值运算totalV5055I15-11 54C1001100104X10100-1010 10094M10001010001094C1001000-100100 1000994M100010010001994最终返回 1994与题目示例 5 完全吻合。可以看到减法组合IV、XC、CM都在反向扫描中被自动识别。五、测试用例与验证该题测试位于 leetcode/0013.Roman-to-Integer/13. Roman to Integer_test.go采用「参数-答案」结构体驱动的表驱动测试type question13 struct { para13 ans13 } type para13 struct { one string } type ans13 struct { one int } func Test_Problem13(t *testing.T) { qs : []question13{ {para13{III}, ans13{3}}, {para13{IV}, ans13{4}}, {para13{IX}, ans13{9}}, {para13{LVIII}, ans13{58}}, {para13{MCMXCIV}, ans13{1994}}, {para13{MCMXICIVI}, ans13{2014}}, {para13{}, ans13{0}}, } for _, q : range qs { a, p : q.ans13, q.para13 got : romanToInt(p.one) if got ! a.one { t.Fatalf(input %q: got %d, want %d, p.one, got, a.one) } } }5.1 用例覆盖分析测试用例不仅覆盖了题目给出的全部五个示例III、IV、IX、LVIII、MCMXCIV还额外补充了两个边界场景MCMXICIVI → 2014混合长字符串的鲁棒性验证 → 0空串边界直接对应源码第 1517 行的空串防护分支。5.2 运行方式在仓库根目录下运行单题测试go test -v ./leetcode/0013.Roman-to-Integer/若希望运行全部题目的测试并输出覆盖率可直接使用仓库自带的 gotest.sh 脚本其内部执行go test -covermodeatomic -coverprofilecoverage.txt ./leetcode/...bash gotest.sh六、与逆运算 12. Integer to Roman 的对照罗马数字相关的另一道题是 LeetCode 第 12 题 Integer to Roman整数转罗马数字本仓库的实现位于 leetcode/0012.Integer-to-Roman/12. Integer to Roman.gofunc intToRoman(num int) string { values : []int{1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1} symbols : []string{M, CM, D, CD, C, XC, L, XL, X, IX, V, IV, I} res, i : , 0 for num ! 0 { for values[i] num { i } num - values[i] res symbols[i] } return res }两道题互为逆运算可对照学习第 13 题将罗马数字解析为整数核心是「识别减法组合」小数在前即减第 12 题将整数编码为罗马数字核心是把四类减法组合CM、CD、XC、XL、IX、IV与常规符号一起按降序贪心取值。值得注意的是第 12 题把900/400/90/40/9/4等减法组合直接编码为独立符号单元这恰好印证了第 13 题反向扫描时「num lastint即做减法」的判定与罗马数字本身的编码结构是自洽的——一个合法罗马数字串中只要出现小数在前的相邻对必然属于六类减法特例之一。七、小结本题的关键要点可归纳为规则本质罗马数字「左减右加」六类减法特例覆盖所有小数在前的情况算法核心一次反向扫描通过与右边已处理字符的数值比较即可同时处理加减无需预判组合实现技巧map 符号表 切片取字符 lastint游标代码简洁且空间复杂度 O(1)工程规范仓库代码遵循 Google Golang Style Guide配套表驱动测试覆盖示例与边界可通过 gotest.sh 一键运行全部测试并生成覆盖率报告。无论是准备面试还是巩固字符串解析基本功将本仓库的 源码实现 与 测试用例 对照研读都是最快掌握该题解法的路径。【免费下载链接】LeetCode-Go✅ Solutions to LeetCode by Go, 100% test coverage, runtime beats 100% | LeetCode 题解项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Go创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考