【LeetCode 题解】算法:8.字符串转换整数(atoi)
一、问题描述
在 LeetCode 的算法题库里,有这样一道题目,要求我们实现一个名为 myAtoi(string s)
的函数,其功能是将给定的字符串转换为一个 32 位有符号整数。具体的转换规则如下:
处理步骤
-
剔除前导空格:读取字符串时,要先把开头无用的空格去除。
-
确定符号:查看下一个字符(前提是未到字符串末尾),若为
-
则结果为负,若为+
则结果为正。若这两个符号都不存在,默认结果为正。 -
读取数字:跳过前面的零,开始读取数字,直至遇到非数字字符或者到达字符串末尾。若未读取到任何数字,结果为 0。
-
范围截断:如果得到的整数超出了 32 位有符号整数的范围
[−2^31, 2^31 − 1]
,需要进行截断处理。即小于−2^31
的整数截断为−2^31
,大于2^31 − 1
的整数截断为2^31 − 1
。 -
返回结果:最后将处理好的整数作为最终结果返回。
示例展示
-
示例 1
-
输入:
s = "42"
-
输出:42
-
解释:字符串无前导空格和符号,直接读取到数字 42。
-
-
示例 2
-
输入:
s = " -042"
-
输出:-42
-
解释:先去除前导空格,再读取到负号,接着读取数字 42(忽略前导零)。
-
-
示例 3
-
输入:
s = "1337c0d3"
-
输出:1337
-
解释:读取到 1337 后,遇到非数字字符 'c',停止读取。
-
-
示例 4
-
输入:
s = "0-1"
-
输出:0
-
解释:仅读取到数字 0,遇到 '-' 停止读取。
-
-
示例 5
-
输入:
s = "words and 987"
-
输出:0
-
解释:第一个字符 'w' 不是数字,直接停止读取。
-
二、思路分析
为了实现 myAtoi
函数,我们可以按照规则,逐步对输入的字符串进行处理。具体思路如下:
-
跳过前导空格:使用一个指针跳过字符串开头的所有空格。
-
判断符号:检查指针指向的字符,若为
-
或+
,记录符号并移动指针。 -
读取数字:从当前指针位置开始,逐个读取数字字符,将其转换为整数。若遇到非数字字符,停止读取。
-
范围判断:在读取数字的过程中,持续检查结果是否超出 32 位有符号整数的范围,若超出则进行截断。
-
返回结果:根据记录的符号,给最终结果加上符号并返回。
三、Java 代码实现
public class StringToInteger {
public static int myAtoi(String s) {
// 去除前导空格
s = s.trim();
if (s.length() == 0) {
return 0;
}
// 判断符号
int sign = 1;
int index = 0;
if (s.charAt(0) == '-') {
sign = -1;
index++;
} else if (s.charAt(0) == '+') {
index++;
}
// 读取整数
int result = 0;
while (index < s.length()) {
char c = s.charAt(index);
if (Character.isDigit(c)) {
int digit = c - '0';
// 判断是否会溢出
if (result > (Integer.MAX_VALUE - digit) / 10) {
return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
result = result * 10 + digit;
} else {
break;
}
index++;
}
return sign * result;
}
public static void main(String[] args) {
String s1 = "42";
System.out.println(myAtoi(s1));
String s2 = " -042";
System.out.println(myAtoi(s2));
String s3 = "1337c0d3";
System.out.println(myAtoi(s3));
String s4 = "0-1";
System.out.println(myAtoi(s4));
String s5 = "words and 987";
System.out.println(myAtoi(s5));
}
}
代码解释
-
去除前导空格:使用
trim()
方法去除字符串开头和结尾的空格。若去除空格后字符串为空,直接返回 0。 -
判断符号:检查字符串的第一个字符,若为
-
,将符号sign
设为 -1,并将指针index
后移一位;若为+
,直接将指针index
后移一位。 -
读取整数:从
index
位置开始遍历字符串,若字符为数字,将其转换为整数并累加到result
中。在累加过程中,需要判断是否会发生溢出。 -
范围判断:通过
result > (Integer.MAX_VALUE - digit) / 10
来判断是否会溢出。若会溢出,根据符号返回相应的边界值。 -
返回结果:最后将结果乘以符号
sign
并返回。
四、复杂度分析
-
时间复杂度:(O(n)),其中 n 是字符串的长度。我们只需遍历字符串一次。
-
空间复杂度:(O(1)),只使用了常数级的额外空间。
感谢各位的阅读,后续将持续给大家讲解力扣中的算法题,如果觉得这篇内容对你有帮助,别忘了点赞和关注,后续还有更多精彩的算法解析与你分享!