尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

手写字符串转整数的完整思路:CS-Notes 剑指 Offer 第 67 题「把字符串转换成整数」详解

手写字符串转整数的完整思路:CS-Notes 剑指 Offer 第 67 题「把字符串转换成整数」详解 手写字符串转整数的完整思路CS-Notes 剑指 Offer 第 67 题「把字符串转换成整数」详解【免费下载链接】CS-Notes:books: 技术面试必备基础知识、Leetcode、计算机操作系统、计算机网络、系统设计项目地址: https://gitcode.com/GitHub_Trending/cs/CS-Notes本篇围绕 CS-Notes 仓库 剑指 Offer 题解 中的第 67 题《把字符串转换成整数》展开覆盖题目要求、原始题解的逐行解析以及原方案在溢出边界上的隐患与加固方法。读完你能掌握不使用库函数手写字符串转整数的完整流程数字字符的累加原理、符号位处理、非法输入判定以及面试中常被追问的溢出检测技巧。题目要求与示例原题见 notes/67. 把字符串转换成整数.md的描述非常简短但约束条件很硬将一个字符串转换成一个整数字符串不是一个合法的数值则返回 0要求不能使用字符串转换整数的库函数。题目给出的输入输出示例Input: 2147483647 1a33 Output: 2147483647 0这两个示例分别对应两类典型情况2147483647带正号且恰好等于Integer.MAX_VALUE应正常转换1a33数字中间夹杂非法字符a属于不合法的数值应返回 0。题目的核心约束——禁止使用库函数——意味着不能写Integer.parseInt(str)或Integer.valueOf(str)之类的调用必须自己完成字符流到数值的翻译过程。这也是本题的考查点考察你是否真正理解字符串、ASCII 码与整数之间的转换机制。核心思路逐位累加手写转换的本质是一个按位展开的过程。对于字符串123其数值等于((0 * 10 1) * 10 2) * 10 3 123也就是从左到右扫描每一位数字字符每读一位就把已有结果乘 10 再加上新的一位。原仓库题解给出的 Java 实现如下完整继承其代码结构public int StrToInt(String str) { if (str null || str.length() 0) return 0; boolean isNegative str.charAt(0) -; int ret 0; for (int i 0; i str.length(); i) { char c str.charAt(i); if (i 0 (c || c -)) /* 符号判定 */ continue; if (c 0 || c 9) /* 非法输入 */ return 0; ret ret * 10 (c - 0); } return isNegative ? -ret : ret; }时间复杂度为 O(n)n 为字符串长度空间复杂度为 O(1)只用了常数额外空间。逐行解析关键实现1. 空串与 null 的兜底if (str null || str.length() 0) return 0;null直接解引用会抛NullPointerException空串没有可转换的数字字符按非法则返回 0的约定统一处理。这类边界检查在面试手写代码中是高频失分点建议养成先判空再遍历的习惯。2. 符号的提前判定boolean isNegative str.charAt(0) -;实现上先记录符号而不是在遍历时直接处理好处是主循环可以专注于数字累加这一件事符号问题最后统一结算return isNegative ? -ret : ret;。3. 符号位只在首位生效if (i 0 (c || c -)) /* 符号判定 */ continue;和-只允许出现在字符串开头出现一次后被continue跳过、不参与累加。注意条件中的i 0这保证了出现在中间位置的/-例如12-34不会被跳过而是落入下一行的非法输入判定、触发返回 0。4. 非法字符即返回 0if (c 0 || c 9) /* 非法输入 */ return 0;利用09在 ASCII 表中连续这一性质用区间判断即可识别数字字符。任何不在此区间内的字符如示例中的1a33的a都说明整个字符串不是一个合法的数值按题意直接返回 0且不允许截断到第一个非法字符为止例如1a33不能返回 1这正是题目示例想强调的语义。5. 累加公式ret ret * 10 (c - 0)ret ret * 10 (c - 0);这是手写转换中最值得说明的一行。c - 0之所以能取出字符对应的数值是因为数字字符在 ASCII 表中按序排列0是 48、1是 49……9是 57所以任意数字字符减去0就得到它代表的 09 数值。这一步本质上是在做ASCII 码到十进制数值的映射理解了它就理解了所有手写数字解析的基础。溢出边界原方案的隐患与加固原仓库的题解简洁高效但从源码结构看它隐含一个边界假设输入数值不会超出int范围。以题目自己的示例2147483647即Integer.MAX_VALUE为界如果输入是2147483648在ret ret * 10 (c - 0)这一步会发生整数溢出ret在乘加过程中越过MAX_VALUE后回绕成负数ret * 10继续失真最终返回一个看似正常的错误结果而不是按题意返回 0。面试场景下建议主动指出这一点并给出加固版本——在每次乘加之前检查是否会越过int的上界public int StrToIntSafe(String str) { if (str null || str.length() 0) return 0; boolean isNegative str.charAt(0) -; int ret 0; for (int i 0; i str.length(); i) { char c str.charAt(i); if (i 0 (c || c -)) continue; if (c 0 || c 9) return 0; int digit c - 0; // 防溢出检查ret*10 digit 是否会越过 int 上界 // 上界按符号区分负数可多容纳一个 -2147483648 int limit isNegative ? Integer.MIN_VALUE : Integer.MAX_VALUE; if (ret (limit - digit) / 10) return 0; ret ret * 10 digit; } return ret; }防溢出判定的核心是ret (limit - digit) / 10它把ret * 10 digit limit变形为不经过乘法的比较避免了检查溢出时溢出已经发生的悖论。对负数一侧int的范围不对称-2147483648比2147483647多一因此上界要用Integer.MIN_VALUE单独处理。为什么题目禁止库函数手写与parseInt的行为差异题目之所以强调不能使用字符串转换整数的库函数不只是形式上的限制而是因为库函数和本题的语义并不一致值得在文章中对比清楚行为Integer.parseInt库函数本题要求的手写实现非法字符串抛出NumberFormatException返回 0超出 int 范围抛出NumberFormatException返回 0见上文溢出加固空串 / null抛出异常返回 0前导/中间非法字符一律视为非法一律视为非法返回 0如1a33→ 0可以看出遇非法就静默返回 0的语义比库函数更宽容也更特殊这正是面试官希望看到你亲手实现的原因——只有在逐字符扫描的过程中才能同时完成符号、合法性、溢出这三类检查。在 CS-Notes 仓库中的位置与相关题本题在仓库中属于 剑指 Offer 题解 - 目录 其它分类下的第 67 题目录文件第 126 行收录原文见 notes/67. 把字符串转换成整数.md。仓库中与它构成解题思路互补的题解还有表示数值的字符串同一系列第 20 题反过来考察判断一个字符串是不是合法数值题解采用正则表达式[-]?\\d*(\\.\\d)?([eE][-]?\\d)?一次性匹配完成。第 67 题的手写循环式校验逐字符判定数字与第 20 题的正则式校验是处理字符串与数值关系的两类典型手段打印从 1 到最大的 n 位数当数字位数大到int/long都装不下时该题解改用char数组存储每一位数字并回溯生成与第 67 题逐位处理数字字符的思路一脉相承。小结手写字符串转整数的骨架是逐位累加ret ret * 10 (c - 0)其依据是数字字符在 ASCII 表中连续排布三类边界必须处理null/空串、非首位的符号或中间非法字符返回 0、以及溢出检测用ret (limit - digit) / 10在乘加前拦截原仓库题解notes/67. 把字符串转换成整数.md覆盖了空串、符号与非法字符的处理但未做溢出防护面试时主动补上防溢出判断并能说清为什么负数上界要用Integer.MIN_VALUE是本题相对原解的主要加分点结合仓库内第 17、20 题一起复习可以形成大数字的字符数组表示 → 字符串数值合法性判定 → 字符串到整数的完整转换这一条完整的字符串数字处理知识链。【免费下载链接】CS-Notes:books: 技术面试必备基础知识、Leetcode、计算机操作系统、计算机网络、系统设计项目地址: https://gitcode.com/GitHub_Trending/cs/CS-Notes创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表