题目
算法思路
本问题的几个关键点:
- 符号位:可能为“+”、“-”,也可能没有,可以新建一个变量保存符号位。
- 字符转数字:用该字符的ASCII码减去“0”的ASCII码即可得到该字符对应的数字。
- 数字拼接:从左向右遍历数字,设当前数字为 x x x,数字结果为 r e s res res,则数字拼接递推公式为 r e s = 10 × r e s + x res=10\times res+x res=10×res+x
- 数字越界处理:每一轮数字拼接之前,先判断
r
e
s
res
res 在拼接后是否会超过 2147483647(
2
31
−
1
2^{31}-1
231−1),若会超过则直接加上符号位返回。
假设 t m p tmp tmp = r e s res res / 10,则拼接后越界有两种情况: t m p > 214748364 tmp>214748364 tmp>214748364 或 t m p = 214748364 tmp=214748364 tmp=214748364且 x > 7 x>7 x>7
具体代码
class Solution {
public int strToInt(String str) {
char[] c = str.trim().toCharArray();//去掉首尾空格后转为字符数组
if(c.length == 0)return 0;
int res = 0, bndry = Integer.MAX_VALUE / 10;
int i = 1, sign = 1;
if(c[0] == '-')sign = -1;//只有在首个字符为"-"时符号位sign才会为-1
else if(c[0] != '+')i = 0;//若首个字符既不是"+"也不是"-"则后面的转数字遍历要从首个字符开始
for(int j = i; j < c.length; j++){
if(c[j] < '0' || c[j] > '9')break;//遇到非数字的字符时跳出循环
if(res > bndry || res == bndry && c[j] > '7')return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;//越界处理
res = res * 10 + (c[j] - '0');//字符转数字,然后拼接数字
}
return sign * res;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n 为字符串长度
- 空间复杂度: O ( n ) O(n) O(n),字符串删除首尾空格后需要建立新字符串,且字符串转为字符数组 c 也是额外空间开销。
代码优化
不用trim()
,直接从头开始遍历字符串,可以降低空间复杂度至
O
(
1
)
O(1)
O(1)。
class Solution {
public int strToInt(String str) {
int res = 0, bndry = Integer.MAX_VALUE / 10;
int i = 0, sign = 1, length = str.length();
if(length == 0)return 0;
//跳过开头空格
while(str.charAt(i) == ' '){
if(++i == length)return 0;
}
if(str.charAt(i) == '-')sign = -1;//只有在首个字符为"-"时符号位sign才会为-1
if(str.charAt(i) == '-' || str.charAt(i) == '+')i++;//若有符号位,则后面的转数字遍历要从下一个字符开始
for(int j = i; j < length; j++){
if(str.charAt(j) < '0' || str.charAt(j) > '9')break;//遇到非数字的字符时跳出循环
if(res > bndry || res == bndry && str.charAt(j) > '7')return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;//越界处理
res = res * 10 + (str.charAt(j) - '0');//字符转数字,然后拼接数字
}
return sign * res;
}
}