在这篇博客中,我们将探讨如何实现一个 myAtoi(string s)
函数,它能够将字符串 s
转换为 32 位有符号整数。我们将详细讨论转换规则、步骤和代码实现,最后分析该算法的时间和空间复杂度。
题目描述
实现一个 myAtoi
函数,将字符串 s
转换为一个 32 位的有符号整数。该函数遵循以下步骤:
- 跳过前导空格:忽略字符串开头的所有空格字符。
- 处理正负号:识别数字的正负。如果出现
+
或-
符号,确定数字是正数还是负数。若没有符号,默认认为数字是正数。 - 读取数字字符:从字符串中读取连续的数字字符,直到遇到非数字字符或到达字符串的末尾。
- 处理越界情况:如果转换后的数字超出了 32 位有符号整数的范围(小于
-2^31
或大于2^31 - 1
),返回范围内的最大或最小值。 - 返回结果:根据符号返回最终的整数值。
示例
- 输入:
"42"
,输出:42
- 输入:
" -42"
,输出:-42
- 输入:
"4193 with words"
,输出:4193
- 输入:
"words and 987"
,输出:0
- 输入:
"-91283472332"
,输出:-2147483648
(越界情况,返回最小值)
详细解题步骤
1. 忽略前导空格
首先,我们需要跳过字符串开头的空格字符,以确保从第一个非空字符开始处理。
2. 处理符号
如果遇到 +
或 -
符号,记录当前的符号。如果未出现符号,默认符号为正。
3. 读取数字部分
从遇到的第一个数字字符开始,将其转换为整数。如果遇到非数字字符,立即停止读取。
4. 处理越界情况
由于整数的范围是有限的,最大值为 2^31 - 1
,最小值为 -2^31
。在转换过程中,需要判断是否即将溢出,提前截断到合法的范围内。
5. 返回结果
结合正负号返回最终的整数结果。
代码实现
class Solution {
public:
int myAtoi(string s) {
int ans = 0;
int count = 0; // 当前已处理多少个字符
bool f = false; // 标记是否是负数
for(char c : s) {
if(c == ' ' && count == 0) continue; // 跳过前导空格
count++;
if(count == 1 && (c == '-' || c == '+')) {
// 判断符号
f = c == '-';
continue;
}
if(c < '0' || c > '9') break; // 非数字字符,停止读取
int dig = c - '0';
// 检查溢出情况
if(ans > (INT_MAX - dig) / 10) return f ? INT_MIN : INT_MAX;
ans = ans * 10 + dig;
}
return f ? -ans : ans; // 返回最终结果
}
};
时间复杂度与空间复杂度
时间复杂度
该算法的时间复杂度为 O(n),其中 n
是输入字符串的长度。我们最多需要遍历整个字符串一次,因此复杂度与字符串长度成线性关系。
空间复杂度
该算法的空间复杂度为 O(1),因为我们只用了有限的额外变量来存储中间结果、符号信息和计数器,并没有依赖额外的动态数据结构。
结论
这道题目通过模拟手动转换的过程,逐步解析字符串并生成整数值。关键点在于如何处理字符串中的空格、符号和数字字符,以及防止结果超出32位整数的范围。通过精心设计的溢出检测机制,我们可以确保算法的正确性和鲁棒性。