十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

LeetCode 8. 字符串转换整数 (atoi) 全解:字符处理、数字拼接与 32 位越界防护(LeetCode-Book 精选 88 题)

LeetCode 8. 字符串转换整数 (atoi) 全解:字符处理、数字拼接与 32 位越界防护(LeetCode-Book 精选 88 题) LeetCode 8. 字符串转换整数 (atoi) 全解字符处理、数字拼接与 32 位越界防护LeetCode-Book 精选 88 题【免费下载链接】LeetCode-Book《剑指 Offer》《图解算法数据结构》《Krahets 笔面试精选 88 题》Python, Java, C 解题代码项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Book本篇技术指南基于 LeetCode-Book 仓库中 《Krahets 笔面试精选 88 题》题解文档.md)系统讲解 LeetCode 第 8 题“字符串转换整数 (atoi)”的完整解法如何分四类处理输入字符、如何用res 10 × res x进行数字拼接以及在“环境只能存储 32 位有符号整数”约束下如何用边界值bndry在拼接前完成越界预判。读完本文你将掌握一套可复现的 Python / Java / C 实现并能在手写 atoi 类问题时举一反三地处理空格、符号位与溢出边界。一、题目核心一个字符串里藏着哪四类字符myAtoi(s)的输入是一个任意字符串根据题意从左到右扫描时只需要考虑以下四种字符其余全部忽略首部空格直接跳过删除即可它们不参与数值转换。符号位只可能出现三种情况即、-或“无符号”。需要新建一个变量保存符号位sign在返回结果前再乘上正负号。非数字字符遇到首个非数字字符时应立即终止解析并返回当前已拼接的结果不再向后扫描。数字字符这是唯一需要“真正拼接”的字符包含两个子步骤——字符转数字与数字拼接详见下一节。这一分类贯穿整个解法先处理空格与符号再逐字符判断是否为数字遇到非数字立即break/return最后统一应用符号位。仓库源码中的注释与文档一致例如 lc_8_string_to_integer_atoi_s1.py 按“删除首尾空格 → 判空 → 处理符号位 → 循环拼接 → 越界拦截”的顺序执行。二、数字拼接公式res 10 × res x若从左向右遍历数字设当前位字符为c当前位数字为x已拼接结果为res则数字拼接公式为res 10 × res x x ascii(c) - ascii(0)其中ascii(c) - ascii(0)即“该数字字符的 ASCII 码”与“0的 ASCII 码”相减从而把字符0~9映射为整数0~9。在三种语言的实现中分别对应Pythonres 10 * res ord(c) - ord(0)ord取字符码点Javares res * 10 (c[j] - 0)char参与算术运算时自动按码点计算Cres res * 10 (s[j] - 0)。以输入 -42为例跳过空格后首字符为-置sign -1随后依次拼接4、2得到res 42最终返回sign * res -42。这个“先拼绝对值、最后统一乘符号”的手法使得正负数共用同一套拼接逻辑代码更简洁。三、32 位整数越界为什么必须在拼接前拦截题目要求返回值的范围是[-2^31, 2^31 - 1]即[-2147483648, 2147483647]并且明确指出“环境只能存储 32 位大小的有符号整数”。这意味着在拼接过程中必须始终保持res处在 int 类型的取值范围内否则在真正发生溢出如 Python 大整数、C 有符号溢出之前就要提前截断。因此在每轮数字拼接之前要先判断res在此轮拼接后是否超过2147483647若超过则带上符号位直接返回最大值或最小值。设拼接边界bndry 2147483647 // 10 214748364则存在以下两种越界情况res bndry 情况一执行拼接后 10 × res ≥ 2147483650必然越界 res bndry 且 x 7 情况二拼接后为 2147483648 或 2147483649越界情况二需要解释bndry × 10 7 2147483647恰好是 int 上限若当前位数字x 7则拼接结果为2147483648或2147483649均超出上限必须按溢出处理。在三种语言中对应的判断写法分别是Pythonif res bndry or res bndry and c 7: return int_max if sign 1 else int_min用字符7与c比较等价于与数字 7 比较Javaif (res bndry || res bndry c[j] 7) return sign 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;Cif (res bndry || res bndry s[j] 7) return sign 1 ? INT_MAX : INT_MIN;其中bndry的取值也随语言略有差异但数值等价Python 中为2 ** 31 // 10Java 中为Integer.MAX_VALUE / 10C 中为INT_MAX / 10结果都是214748364。仓库中 lc_8_string_to_integer_atoi_s2.java 与 lc_8_string_to_integer_atoi_s1.cpp 均以Integer.MAX_VALUE / 10、INT_MAX / 10初始化该边界。四、方案一先trim()/strip()再解析空间 O(N)第一种实现直接调用语言的去空格 API先删除首尾空格再解析逻辑直观、最贴近题面描述。Python 实现class Solution: def myAtoi(self, s: str) - int: s s.strip() # 删除首尾空格 if not s: return 0 # 字符串为空则直接返回 res, i, sign 0, 1, 1 int_max, int_min, bndry 2 ** 31 - 1, -2 ** 31, 2 ** 31 // 10 if s[0] -: sign -1 # 保存负号 elif s[0] ! : i 0 # 若无符号位则需从 i 0 开始数字拼接 for c in s[i:]: if not 0 c 9 : break # 遇到非数字的字符则跳出 if res bndry or res bndry and c 7: return int_max if sign 1 else int_min # 数字越界处理 res 10 * res ord(c) - ord(0) # 数字拼接 return sign * res关键点在于首字符为-时sign -1且i 1首字符为时保持i 1跳过符号位首字符是数字或其它字符时i 0直接从首位开始拼接。仓库文件 lc_8_string_to_integer_atoi_s1.py 与此实现逐行一致。Java 实现class Solution { public int myAtoi(String s) { char[] c s.trim().toCharArray(); if (c.length 0) return 0; int res 0, bndry Integer.MAX_VALUE / 10; int i 1, sign 1; if (c[0] -) sign -1; else if (c[0] ! ) i 0; for (int j i; j c.length; j) { if (c[j] 0 || c[j] 9) break; if (res bndry || res bndry c[j] 7) return sign 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE; res res * 10 (c[j] - 0); } return sign * res; } }方案一复杂度分析时间复杂度 O(N)N为字符串长度线性遍历一次字符串占用 O(N) 时间。空间复杂度 O(N)删除首尾空格后需建立新字符串Python 的strip()、Java 的trim().toCharArray()都会产生新的字符串/字符数组对象最差情况下占用 O(N) 额外空间。五、方案二手动跳过空格空间 O(1)若不使用trim() / strip()删除首部空格而是改为“遍历跳过空格”的方式则无需构造新字符串可将空间复杂度降低至 O(1)。这也更贴近 C 语言手写atoi的经典风格。Python 实现class Solution: def myAtoi(self, s: str) - int: res, i, sign, length 0, 0, 1, len(s) int_max, int_min, bndry 2 ** 31 - 1, -2 ** 31, 2 ** 31 // 10 if not s: return 0 # 空字符串提前返回 while s[i] : i 1 if i length: return 0 # 字符串全为空格提前返回 if s[i] -: sign -1 if s[i] in -: i 1 for j in range(i, length): if not 0 s[j] 9 : break if res bndry or res bndry and s[j] 7: return int_max if sign 1 else int_min res 10 * res ord(s[j]) - ord(0) return sign * res该实现与前者的差异集中在两点一是用while s[i] 循环手动推进下标跳过空格并在i到达末尾时返回0说明字符串全为空格二是用if s[i] in -: i 1一次性跳过符号位而不再区分与无符号的情况。仓库文件 lc_8_string_to_integer_atoi_s2.py 与此实现一致。Java 实现class Solution { public int myAtoi(String s) { int res 0, bndry Integer.MAX_VALUE / 10; int i 0, sign 1, length s.length(); if(length 0) return 0; while(s.charAt(i) ) if(i length) return 0; if(s.charAt(i) -) sign -1; if(s.charAt(i) - || s.charAt(i) ) i; for(int j i; j length; j) { if(s.charAt(j) 0 || s.charAt(j) 9) break; if(res bndry || res bndry s.charAt(j) 7) return sign 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE; res res * 10 (s.charAt(j) - 0); } return sign * res; } }C 实现class Solution { public: int myAtoi(string s) { int res 0, bndry INT_MAX / 10; int i 0, sign 1, length s.size(); if(length 0) return 0; while(s[i] ) if(i length) return 0; if(s[i] -) sign -1; if(s[i] - || s[i] ) i; for(int j i; j length; j) { if(s[j] 0 || s[j] 9) break; if(res bndry || res bndry s[j] 7) return sign 1 ? INT_MAX : INT_MIN; res res * 10 (s[j] - 0); } return sign * res; } };方案二复杂度分析时间复杂度 O(N)仍为单次线性扫描N为字符串长度。空间复杂度 O(1)全程只使用若干整数变量与下标不创建新字符串额外空间与输入规模无关。六、仓库源码印证与本地运行方式本仓库《Krahets 笔面试精选 88 题》selected_coding_interview为本题提供了与上述两种方案一一对应的三种语言实现可直接对照阅读方案PythonJavaC方案一strip/trimlc_8_string_to_integer_atoi_s1.pylc_8_string_to_integer_atoi_s1.java—方案二手动跳空格lc_8_string_to_integer_atoi_s2.pylc_8_string_to_integer_atoi_s2.javalc_8_string_to_integer_atoi_s1.cpp从源码结构看Python 与 Java 均给出 s1/s2 两版实现C 则直接采用空间 O(1) 的手动跳空格版本恰好印证了“优先使用 O(1) 空间写法”这一实践倾向。源码文件统一以from include import *Python、package lc_8_string_to_integer_atoi; import include.*;Java、#include ../include/include.hppC引入仓库公共头文件并附带main/ 驱动代码与测试用例占位可在此基础上替换test_input验证各类输入# 以 Python 方案一为例 from include import * class Solution: def myAtoi(self, s: str) - int: s s.strip() if not s: return 0 res, i, sign 0, 1, 1 int_max, int_min, bndry 2 ** 31 - 1, -2 ** 31, 2 ** 31 // 10 if s[0] -: sign -1 elif s[0] ! : i 0 for c in s[i:]: if not 0 c 9 : break if res bndry or res bndry and c 7: return int_max if sign 1 else int_min res 10 * res ord(c) - ord(0) return sign * res slt Solution() for t in [ -42, 4193 with words, words and 987, -91283472332, 1, , 2147483648]: print(f{t!r:20} - {slt.myAtoi(t)})建议用以下用例自测覆盖题面全部边界 -42→-42前导空格 负号4193 with words→4193数字后遇到非数字截断words and 987→0首个非空字符非数字直接返回 0-91283472332→-2147483648负向越界返回INT_MIN2147483648→2147483647正向越界返回INT_MAX →0全空格方案二在跳空格时提前返回。七、小结这道题在考什么字符串转换整数 (atoi) 是面试中典型的“模拟 边界”题考点集中在字符分类能力能否条理清晰地处理空格、符号、非数字与数字四类情况数字拼接功底res 10 × res x与 ASCII 码相减取数字越界防御思维在 32 位 int 约束下用bndry INT_MAX / 10结合“res bndry或res bndry 当前位 7”在拼接前拦截溢出而不是等溢出发生后再补救空间优化意识同一逻辑可写出空间 O(N)依赖strip/trim与空间 O(1)手动跳空格两种版本理解二者的取舍。本仓库对应的剑指 Offer 版本题解位于 sword_for_offer/docs/剑指 Offer 67. 把字符串转换成整数.md可对照学习同一考点在《剑指 Offer》中的变体考查方式更多“模拟 边界”类题目与配套三语言代码可在 selected_coding_interview 目录下按题目编号继续检索。【免费下载链接】LeetCode-Book《剑指 Offer》《图解算法数据结构》《Krahets 笔面试精选 88 题》Python, Java, C 解题代码项目地址: https://gitcode.com/GitHub_Trending/le/LeetCode-Book创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表