Leetcode算法题:字符串转换整数(atoi)
题解:实现 atoi
函数
题目描述:
实现一个 atoi
函数,能够将字符串转换为一个整数。该函数会忽略前导空格,并处理可选的符号(+
或 -
),直到遇到非数字字符为止。若字符串中的数字超出了 32 位带符号整数的范围,返回 Integer.MAX_VALUE
或 Integer.MIN_VALUE
。
题目要求:
-
只允许处理数字,符号(
+
或-
)以及空格字符。 -
返回转换后的整数值。若遇到溢出情况,返回
Integer.MAX_VALUE
或Integer.MIN_VALUE
。 -
对于无效输入(如字符串中没有数字),返回 0。
解题思路:
-
去除前导空格:
-
根据题目要求,输入字符串可能包含前导空格。我们需要去除这些空格,直到遇到第一个有效字符(数字或符号)。
-
通过一个
while
循环逐步遍历字符,直到找到第一个非空格字符,更新字符串的起始位置。
-
-
处理符号位:
-
在去除空格后,可能会遇到一个符号字符(
+
或-
)。如果遇到-
,我们需要记住这个符号,之后将转换后的结果乘以 -1。如果遇到+
,则继续处理下一个字符。 -
注意:这里不能使用
for
循环,因为我们不应该扫描整个字符串中的每一个符号,应该只在符号字符后处理一次符号。
-
-
解析数字:
-
在处理完符号后,接下来解析字符串中的数字部分。遍历字符直到遇到非数字字符(如字母、空格等)。
-
每遇到一个数字字符,就将其转换为对应的整数值(通过
charAt(i) - '0'
)。然后将之前的数字结果乘以 10 并加上当前的数字。
-
-
溢出检查:
-
在数字解析过程中,需要时刻检查是否会发生溢出。具体来说,如果当前
num
已经大于Integer.MAX_VALUE / 10
,那么再乘以 10 就会溢出。如果num
等于Integer.MAX_VALUE / 10
,那么还需要进一步检查当前数字是否大于Integer.MAX_VALUE % 10
,以确定是否溢出。 -
若发生溢出,应该返回
Integer.MAX_VALUE
或Integer.MIN_VALUE
,具体取决于符号。
-
-
返回结果:
-
将解析出的数字乘上符号(
mark
)后返回结果。
-
代码实现:
class Solution {public int myAtoi(String s) {int mark = 1; // 标记符号,默认为正数int num = 0; // 存储转换后的数字int i = 0; // 遍历字符串的指针// 1. 去除前导空格while (i < s.length() && s.charAt(i) == ' ') {i++;}// 2. 如果字符串为空或仅包含空格,返回 0if (i == s.length()) {return 0;}// 3. 处理符号位if (s.charAt(i) == '-') {mark = -1;i++;} else if (s.charAt(i) == '+') {i++;}// 4. 解析数字部分while (i < s.length() && Character.isDigit(s.charAt(i))) {int digit = s.charAt(i) - '0';// 5. 检查是否发生溢出if (num > Integer.MAX_VALUE / 10 || (num == Integer.MAX_VALUE / 10 && digit > Integer.MAX_VALUE % 10)) {return mark == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;}// 更新数字num = num * 10 + digit;i++;}// 6. 返回最终结果return num * mark;}
}
代码分析:
-
去除前导空格:
-
使用
while
循环检查字符串中的每个字符,直到遇到第一个非空格字符。这样,我们可以确保从有效字符开始解析。
-
-
处理符号位:
-
如果遇到
-
,我们将mark
设置为 -1,表示结果为负数。如果是+
,则继续处理。 -
对符号的处理只需要一次,因此我们在符号后直接跳过。
-
-
解析数字:
-
每次遇到数字字符时,通过
charAt(i) - '0'
将字符转换为对应的数字,并累积到num
变量中。这样就实现了逐位构建整数的功能。
-
-
溢出检查:
-
在每次更新
num
时,我们先检查是否会发生溢出。如果会溢出,直接返回Integer.MAX_VALUE
或Integer.MIN_VALUE
。
-
-
最终结果:
-
处理完所有字符后,返回结果
num
,并根据符号进行调整。
-
时间复杂度:
-
时间复杂度:O(n),其中
n
是字符串s
的长度。我们只遍历字符串一次,处理每个字符的时间是常数级别的。 -
空间复杂度:O(1),我们只用了少量的额外空间来存储标记符号、数字结果和遍历指针。
边界情况:
-
输入为空或只有空格时,返回 0。
-
输入包含符号
+
或-
时,正确解析符号。 -
输入中包含非数字字符时,忽略这些字符,只解析数字部分。
-
超过整数范围时,返回
Integer.MAX_VALUE
或Integer.MIN_VALUE
。
总结:
-
本题的关键是如何正确地处理前导空格、符号、数字部分的解析以及溢出检测。
-
通过分步实现每个功能,我们确保了代码的清晰和准确性,同时也考虑了所有可能的边界情况,如溢出、无效字符等。