#8 字符串模拟 中等

字符串转换整数 (atoi)

在 LeetCode 上查看 ↗

🎧 语音讲解

开车或通勤时可听,跟着思路走一遍

速度

📋 题目描述

请你实现一个 myAtoi(string s) 函数,将字符串转换成一个 32 位有符号整数。规则:先丢弃前导空格;然后可选地读取一个正负号;接着尽可能多地读取连续数字;将结果限制在 [−2³¹, 2³¹−1] 内,越界则取边界值。

示例 1

输入:s = "42"
输出:42

示例 2

输入:s = " -42 abc"
输出:-42

示例 3

输入:s = "words and 987"
输出:0(第一个非空字符不是数字或符号)

💭 模拟答题者思考

1. 这是一道模拟题,关键是严格按「空格 → 符号 → 数字」的顺序处理,遇到非法就停。

2. 只在开头跳一次前导空格;符号最多一个;数字一直读到非数字为止。

3. 溢出处理:每累加一位就检查 sign*num 是否已超出 32 位范围,超了直接返回边界值。

4. 首个有效字符若不是数字或符号,直接返回 0。

🧠 变量语义(先读这三句再编码)

变量类型语义(三句法)
iint定义:当前扫描到的位置
维护:依次跳过空格、符号、数字
更新:每处理一个字符 i++
signint定义:正负号(+1 / -1)
维护:只在符号位设置一次
更新:遇到 '-' 置 -1,'+' 置 +1
numint定义:目前累积的数字(绝对值)
维护:每读一位 num = num*10 + 该位
更新:累积后立即用 sign*num 判断是否越界并截断

⌨️ 落码步骤

1. i = 0,跳过所有前导空格

2. 若当前是 '+'/'-',记录 sign 并 i++

3. 循环读数字:num = num*10 + (c - '0')

4. 每步判断 sign*num 是否 ≤ INT_MIN 或 ≥ INT_MAX,越界返回边界

5. 返回 sign * num

💻 代码实现

class Solution:
    def myAtoi(self, s: str) -> int:
        INT_MIN, INT_MAX = -2**31, 2**31 - 1
        i, n = 0, len(s)
        while i < n and s[i] == ' ':      # 1. 跳过前导空格
            i += 1
        sign = 1
        if i < n and s[i] in '+-':        # 2. 处理符号
            sign = -1 if s[i] == '-' else 1
            i += 1
        num = 0
        while i < n and s[i].isdigit():   # 3. 逐位累积
            num = num * 10 + int(s[i])
            i += 1
            if sign * num <= INT_MIN:     # 4. 提前判溢出并截断
                return INT_MIN
            if sign * num >= INT_MAX:
                return INT_MAX
        return sign * num
class Solution {
public:
    int myAtoi(string s) {
        int i = 0, n = s.size();
        while (i < n && s[i] == ' ') i++;        // 1. 跳过空格
        int sign = 1;
        if (i < n && (s[i] == '+' || s[i] == '-')) {
            sign = (s[i] == '-') ? -1 : 1;       // 2. 符号
            i++;
        }
        long num = 0;                            // 用 long 累积防溢出
        while (i < n && isdigit(s[i])) {
            num = num * 10 + (s[i] - '0');       // 3. 累积
            i++;
            if (sign * num <= INT_MIN) return INT_MIN;   // 4. 截断
            if (sign * num >= INT_MAX) return INT_MAX;
        }
        return (int)(sign * num);
    }
};
// 时间 O(n),空间 O(1)

📈 复杂度分析

时间复杂度 O(n)
空间复杂度 O(1)

⚠️ 常见坑

前导空格只在最开头跳;数字中间或之后的空格意味着结束。

符号最多一个,"+-2" 这类第二个符号即非法,停止读取。

边累积边判溢出并截断到 INT_MIN/INT_MAX,不要等全部读完再判。

🔍 必测边界 Case

Case 1:仅空格
s = " " → 0
Case 2:正溢出
s = "91283472332" → 2147483647
Case 3:符号后无数字
s = "+" → 0