题目重点:题目仅给 123→123;先确定空白、符号、数字前缀和溢出契约,再给 32 位训练实现。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 展示的训练契约允许前导 ASCII 空格、可选 +/-、随后最长 ASCII 数字前缀;没有数字返回 0。
- 训练版把结果截到 int32 [-2^31,2^31−1];题目没有规定 clamp、异常还是大整数,现场必须先问。
解题路线
- 用游标跳过前导空格、识别至多一个符号,接着逐位累积十进制数;遇非数字停止。
- 累积时按符号的允许绝对值上限提前截断,避免固定宽度语言先溢出再比较。
- 空串、全空格、只有符号、前导零、后缀文字、正负边界各手算一次。
- 若真实题意只接受纯数字字符串,可进一步简化为逐字符校验;不要把训练扩展误称原题要求。
手动走一遍
‘ -42tail’ 在训练版返回 -42;‘2147483648’ 截为 2147483647;‘123’ 返回 123。只有最后一个是题目提供的例子。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def atoi_training(text):
"""Training contract: spaces, optional sign, digit prefix, int32 clamp."""
i = 0
while i < len(text) and text[i] == " ":
i += 1
sign = 1
if i < len(text) and text[i] in "+-":
sign = -1 if text[i] == "-" else 1
i += 1
value = 0
while i < len(text) and "0" <= text[i] <= "9":
digit = ord(text[i]) - ord("0")
value = min(value * 10 + digit, 2**31 if sign < 0 else 2**31 - 1)
i += 1
return sign * value
复杂度
扫描最多 n 个字符,O(n) 时间、O(1) 附加空间;Python 大整数在计算中仍可能暂增,但代码逐位截断。
易错点与追问
容易失分的边界
- 不澄清 int32 溢出策略。
- 接受 Unicode 数字却面试语言只支持 ASCII。
- 符号出现两次仍解析。
- 先乘再加在 C++/Java 固定整数里溢出。
继续深挖
- 非法字符返回错误还是停止?
- 支持十六进制或 Unicode 数字?
- 若需要 64 位怎么改边界?
