当前位置: 首页 > news >正文

CodeTop Top 300 热门题目5-字符串转换整数 (atoi)

力扣8题-字符串转换整数(atoi),经典面试题

importredefmyAtoi(s:str)->int:""" 字符串转换整数 (atoi) - 力扣8题 实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数。 算法步骤: 1. 丢弃无用的前导空格 2. 检查第一个字符(假设还没到末尾)是 '+' 还是 '-',读取该符号 3. 读入数字,直到下一个非数字字符或到达输入的末尾 4. 将数字转换为整数(例如,"123" -> 123,"0032" -> 32) 5. 如果没有读入数字,则整数为 0 6. 如果整数超过 32 位有符号整数范围 [-2^31, 2^31-1],截断为该范围 时间复杂度:O(n),空间复杂度:O(1) """# ====== 第一步:去除前导空格 ======s=s.strip()ifnots:return0# ====== 第二步:判断符号 ======sign=1# 默认正号index=0ifs[0]=='-':sign=-1index=1elifs[0]=='+':index=1# 如果第一个字符是数字,index 保持为 0# ====== 第三步:读取数字 ======result=0INT_MAX=2**31-1# 2147483647INT_MIN=-2**31# -2147483648whileindex<len(s)ands[index].isdigit():# 获取当前数字字符的值digit=int(s[index])# ====== 第四步:检查溢出(关键!)=======# 在相加之前判断是否会溢出ifresult>(INT_MAX-digit)//10:# 如果是正数,返回 INT_MAX# 如果是负数,返回 INT_MINreturnINT_MAXifsign==1elseINT_MIN# 当前位累加result=result*10+digit index+=1# 应用符号returnsign*result# ====== 方法二:使用正则表达式(简洁但效率稍低)======defmyAtoi_regex(s:str)->int:""" 使用正则表达式的解法 正则表达式解释: ^[\+\-]? # 可选的正负号 \d+ # 一个或多个数字 """pattern=r'^[\+\-]?\d+'match=re.match(pattern,s.strip())ifnotmatch:return0# 提取匹配到的数字字符串num_str=match.group()# 转换为整数并处理溢出INT_MAX=2**31-1INT_MIN=-2**31num=int(num_str)# 处理溢出ifnum>INT_MAX:returnINT_MAXifnum<INT_MIN:returnINT_MINreturnnum# ====== 方法三:自动机(状态机)解法(进阶)======defmyAtoi_dfa(s:str)->int:""" 使用确定性有限自动机(DFA)的解法 状态定义: - start: 初始状态 - signed: 已读取符号 - in_number: 正在读取数字 - end: 结束状态 状态转移: start -> start (空格) start -> signed (+/-) start -> in_number (数字) start -> end (其他) ...以此类推 """# 定义状态转移表# 状态: [空格, 符号(+/-), 数字, 其他]state_table={'start':['start','signed','in_number','end'],'signed':['end','end','in_number','end'],'in_number':['end','end','in_number','end'],'end':['end','end','end','end']}# 当前状态state='start'sign=1result=0INT_MAX=2**31-1INT_MIN=-2**31forcharins:# 判断字符类型ifchar==' ':char_type=0# 空格elifcharin'+-':char_type=1# 符号elifchar.isdigit():char_type=2# 数字else:char_type=3# 其他# 状态转移state=state_table[state][char_type]# 根据状态执行操作ifstate=='signed':sign=1ifchar=='+'else-1elifstate=='in_number':digit=int(char)# 检查溢出ifresult>(INT_MAX-digit)//10:returnINT_MAXifsign==1elseINT_MIN result=result*10+digitreturnsign*result# ====== 测试用例 ======if__name__=="__main__":# 测试用例1:正常情况print(myAtoi("42"))# 输出: 42# 测试用例2:带前导空格和负号print(myAtoi(" -42"))# 输出: -42# 测试用例3:前导空格和正号print(myAtoi("4193 with words"))# 输出: 4193# 测试用例4:非数字开头print(myAtoi("words and 987"))# 输出: 0# 测试用例5:正号后无数字print(myAtoi("+-12"))# 输出: 0# 测试用例6:正溢出print(myAtoi("91283472332"))# 输出: 2147483647 (INT_MAX)# 测试用例7:负溢出print(myAtoi("-91283472332"))# 输出: -2147483648 (INT_MIN)# 测试用例8:边界值测试print(myAtoi("2147483647"))# 输出: 2147483647 (刚好INT_MAX)print(myAtoi("-2147483648"))# 输出: -2147483648 (刚好INT_MIN)# 测试用例9:前导零print(myAtoi(" -0000000000000012"))# 输出: -12# 测试用例10:测试正则版本print(myAtoi_regex("4193 with words"))# 输出: 4193# 测试用例11:测试DFA版本print(myAtoi_dfa(" -42"))# 输出: -42

详细解释

题目难点

这题看似简单,但有很多边界条件需要处理:

  1. 前导空格" 42"42
  2. 正负号"+42""-42"
  3. 非数字字符终止"4193 with words"4193
  4. 前导零"00042"42
  5. 无效输入"words 42"0
  6. 正溢出"91283472332"2147483647
  7. 负溢出"-91283472332"-2147483648

方法一:常规解法(推荐)

核心步骤

  1. 去除空格strip()去除前导和后导空格
  2. 判断符号:检查第一个字符是否为+-
  3. 读取数字:遍历字符,遇到非数字停止
  4. 处理溢出:关键!在累加之前判断是否会溢出

溢出判断的关键

ifresult>(INT_MAX-digit)//10:returnINT_MAXifsign==1elseINT_MIN

为什么要这样判断?

  • 下一步是result * 10 + digit
  • 如果result * 10 + digit > INT_MAX就会溢出
  • 移项:result > (INT_MAX - digit) // 10

注意:判断要在乘法之前,不能等溢出后再判断!

方法二:正则表达式

优点:代码简洁
缺点:效率稍低,但面试中也常用

正则^[\+\-]?\d+解释:

  • ^字符串开始
  • [\+\-]?可选的正负号
  • \d+一个或多个数字

方法三:状态机(DFA)

适用场景

  • 对状态变化有严格要求
  • 需要清晰的状态转移逻辑
  • 面试官要求"设计一个状态机"

状态转移表

当前状态 \ 输入字符 空格 符号 数字 其他 start start signed in_number end signed end end in_number end in_number end end in_number end end end end end end

复杂度分析

方法时间复杂度空间复杂度
常规解法O(n)O(1)
正则解法O(n)O(n)
DFA解法O(n)O(1)

n 是字符串长度

易错点总结

  1. 溢出判断时机:要在累加前判断,不是累加后
  2. 符号处理:符号只有第一个字符才有效,后续的+-会终止解析
  3. 前导零:直接转整数即可,int()会自动处理
  4. 空字符串strip()后要检查是否为空
  5. 负溢出边界-2147483648是有效的,不要错误处理

http://www.jsqmd.com/news/700268/

相关文章:

  • 毕业论文用DeepSeek V4写,2026年4月嘎嘎降AI到6% - 我要发一区
  • DeepSeek V4内容去AI味对比,2026年4月3款工具实测 - 我要发一区
  • DeepSeek V4 vs ChatGPT写论文,2026年4月哪个AI率低 - 我要发一区
  • GitHub 1.2 万星 Qt 项目 VNote 源码解读(二):Markdown 文本渲染
  • DeepSeek V4写论文降AI率指南,2026年4月嘎嘎实测 - 我要发一区
  • excel合并
  • Phi-mini-MoE-instruct多场景:代码审查、算法解释、面试题生成一体化
  • DeepSeek V4论文降AI率横评,2026年4月嘎嘎降AI第一 - 我要发一区
  • DeepSeek V4内容AI痕迹太重怎么办?2026年4月3步搞定 - 我要发一区
  • 800V高压锂电池生产厂家推荐(工业级与特种定制方案解析)【浩博电池】
  • 结婚如何使用手机进行现场录礼,请人收礼?
  • sb-KafkaListener 20260425
  • Hexo+Qexo全自动化博客搭建教程
  • HTD——基于触觉预测的人形行走-操作框架:融合视觉、本体感知、力反馈、触觉,同时预测动作、未来手部关节受力、由EMA目标编码器监督的未来触觉潜变量
  • openwrt路由器lan口莫名其妙断网的补丁式解决方案
  • Open XML SDK 完全指南:告别手动处理Office文档的烦恼
  • 西恩士行业黑马 液冷阀门清洁度污染物分析系统 - 工业设备研究社
  • LFM2.5-VL-1.6B惊艳案例:老旧文档扫描件OCR+结构化摘要生成效果对比
  • 2026雅思机构实测|零基础必看:多次元、新东方、新航道、环球怎么选 - 速递信息
  • mysql如何防止用户通过子查询窃取权限_MySQL安全参数设置
  • Qwen3.5-2B中小企业AI落地方案:低成本GPU算力适配图文智能客服
  • 全网都追捧的 Kaparthy LLM Wiki 我自己实现了一个
  • DeepSeek V4降AI痕迹完整流程,2026年4月7步走通 - 我要发一区
  • 华为OD机试真题 新系统 2026-04-19 C语言 实现【8位LED控制器】
  • keysight N9040B是德 UXA 频谱分析仪 2 Hz 至 50 GHz
  • 基于倒排索引的 Java 文档搜索引擎(三)
  • 短期备考雅思必看|1-3个月冲刺选机构实测:5家对比,多次元凭什么稳赢 - 速递信息
  • Xiaomi MiMo-V2.5 系列大模型开启公测
  • Hydra:面向超级个体的分布式操作系统基座设计与实战
  • 028、工程化进阶:容错、重试与降级策略