题目重点:基于 Netflix 电面三阶段约束,用逐位累积与加入前预检查处理非法字符、负数最小值、溢出和前导零。
题意与假设
这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。
- 训练版使用可配置 [minimum,maximum],默认 32 位有符号范围;题目只说 overflow,未指定 32/64 位。
- 只允许 ASCII 数字和首字符一个负号,不允许 +、空格或其他字符。
- 把‘只有一位 leading zero 有效’解释为 0 或 01–09 可接受,001 等拒绝;题目未明确具体样例,应面试澄清 00 与 -01 的规则。
解题路线
- 先取可选首位负号,检查剩余数字非空;前导零规则在累积前单独判断。
- 逐个字符检查 ASCII 数字,累积前使用 `value > (limit-digit)//10` 判溢出,负数的 limit 用 -minimum,使 -2147483648 可以通过。
- 末尾应用符号并复核配置范围;中途负号、字母、特殊字符都走输入错误,与数值溢出区分。
手动走一遍
默认 32 位下,`-2147483648` 成功,`2147483648` 在加入最后一位前报溢出;`01` 按训练约定返回 1,`001` 报前导零错误,`12-3` 报非法字符。
Python 参考实现
下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。
代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。
def parse_signed_integer(text, minimum=-(2**31), maximum=2**31 - 1):
"""Training contract: one optional leading '-', at most one leading zero."""
if not text or minimum > 0 or maximum < 0:
raise ValueError("invalid input or bounds")
negative = text[0] == "-"
digits = text[1:] if negative else text
if not digits or (len(digits) > 2 and digits[0] == "0"):
raise ValueError("invalid digits or leading zeros")
limit = -minimum if negative else maximum
value = 0
for char in digits:
if not ("0" <= char <= "9"):
raise ValueError("invalid character")
digit = ord(char) - ord("0")
if value > (limit - digit) // 10:
raise OverflowError("integer overflow")
value = value * 10 + digit
result = -value if negative else value
if not minimum <= result <= maximum:
raise OverflowError("integer overflow")
return result
复杂度
长度 n 的字符串扫描 O(n),只维护累计值与索引,额外空间 O(1);当前 Python 切片 `text[1:]` 会额外复制 O(n),面试若严格要求 O(1) 空间可改为起始下标遍历。
易错点与追问
容易失分的边界
- 使用内置 int/valueOf 绕过题目核心要求。
- 正负数共用正最大值做溢出界,误拒最小负数。
- 仅检查开头负号,不检查中途出现的负号。
- 把 Unicode 数字字符当作 ASCII 接受。
- 没有确认前导零和整型位宽就把训练约定称为原题规则。
继续深挖
- 改成 64 位范围时如何保持同一代码?
- 如果要接受前后空格、+ 号或任意进制,验证顺序怎么变?
- 若语言的中间计算也可能溢出,如何先用阈值比较再乘 10?
