题解地址:https://leetcode-cn.com/problems/string-to-integer-atoi/solution/jin-liang-bu-shi-yong-ku-han-shu-nai-xin-diao-shi-/
这个问题其实没有过多的技巧,考察的是细心和耐心,并且需要不断地调试。在这里我简单罗列几个要点。
Java 、Python 和 C++ 字符串的设计都是不可变的,即使用 trim()
会产生新的变量,因此我们尽量不使用库函数,使用一个变量 index
去做线性遍历,这样遍历完成以后就得到转换以后的数值。
- 根据示例 1,需要去掉前导空格;
- 根据示例 2,需要判断第 1 个字符为
+
和-
的情况,因此,可以设计一个变量sign
,初始化的时候为1
,如果遇到-
,将sign
修正为-1
; - 判断是否是数字,可以使用字符的 ASCII 码数值进行比较,即
0 <= c <= '9'
; - 根据示例 3 和示例 4 ,在遇到第 1 个不是数字的字符的情况下,就得退出循环;
- 根据示例 5,如果转换以后的数字超过了
int
类型的范围,需要截取。这里需要将结果res
变量设计为long
类型,注意:由于输入的字符串转换以后也有可能超过long
类型,因此需要在循环内部就判断是否越界,只要越界就退出循环,这样也可以减少不必要的计算; - 因为涉及下标访问,因此全程需要考虑数组下标是否越界的情况。
特别注意:
由于题目中说“环境只能保存 32 位整数”,因此这里在每一轮循环之前先要检查乘以 10 10 10 以后是否溢出,具体细节请见编码;
Java 代码:
public class Solution {
public int myAtoi(String str) {
int len = str.length();
// 去除前导空格
int index = 0;
while (index < len) {
if (str.charAt(index) != ' ') {
break;
}
index++;
}
if (index == len) {
return 0;
}
// 第 1 个字符如果是符号,判断合法性,并记录正负
int sign = 1;
char firstChar = str.charAt(index);
if (firstChar == '+') {
index++;
sign = 1;
} else if (firstChar == '-') {
index++;
sign = -1;
}
// 不能使用 long 类型,这是题目说的
int res = 0;
while (index < len) {
char currChar = str.charAt(index);
// 判断合法性
if (currChar > '9' || currChar < '0') {
break;
}
// 题目中说:环境只能存储 32 位大小的有符号整数,因此,需要提前判断乘以 10 以后是否越界
if (res > Integer.MAX_VALUE / 10 || (res == Integer.MAX_VALUE / 10 && (currChar - '0') > Integer.MAX_VALUE % 10)) {
return Integer.MAX_VALUE;
}
if (res < Integer.MIN_VALUE / 10 || (res == Integer.MIN_VALUE / 10 && (currChar - '0') > -(Integer.MIN_VALUE % 10))) {
return Integer.MIN_VALUE;
}
// 每一步都把符号位乘进去
res = res * 10 + sign * (currChar - '0');
index++;
}
return res;
}
}
复杂度分析:
- 时间复杂度: O ( N ) O(N) O(N),这里 N N N 为字符串的长度;
- 空间复杂度: O ( 1 ) O(1) O(1)。