题目及例子如上。
本题核心的问题,就是根据字符串str来生成int型数值。比较简便的是从字符串的左边向右边生成:
for (int i = 0; i < str.length(); i++) {
ans = ans * 10 + str.charAt(i) - '0'; //将对应的'x'转换为实际的x数值
}
这个核心问题解决之后,关键就是要得到符合我们要求的str,即str全为数字
1.用flag去应对str首字母为+或者-的情况
2.可以用String的trim()函数得到一个去除首尾空格的字符串,不采用这种方式的话可以用循环来实现trim函数的功能,以节省空间。
3.还有一个关键的点是,题目中说明了只能存储32位有符号整数,即存储范围为\[{\rm{[ - }}{{\rm{2}}^{{\rm{31}}}},{2^{31}} - 1]\],即范围是Integer.MIN_VALUE和Integer.MAX_VALUE
因此我们根据str生成数值的时候,要提前一步判断是否溢出。因为每次ans = ans * 10 + str.charAt(i) - '0',即至少是前一个ans * 10,那么我们就可以根据Integer.MAX_VALUE /10 作为一个评判标准,然后根据此时需要加上的str.charAt(i)来判断新生成的ans会不会溢出。
代码一:时间复杂度:O(N),空间复杂度:O(N),运用了trim()函数生成新的字符串
class Solution {
public int strToInt(String str) {
if (str == null || str.equals("")) return 0;
char[] num = str.trim().toCharArray();
if (num.length == 0) return 0;
int status = 1, left = 1, ans = 0;
if (num[0] == '-') {
status = -1;
} else if (num[0] != '+') {
left = 0;
}
int check = Integer.MAX_VALUE / 10;
for (int i = left; i < num.length; i++) {
if (num[i] < '0' || num[i] > '9') break;
if (ans > check || (ans == check && num[i] > '7')) return status == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
ans = ans * 10 + num[i] - '0';
}
return status * ans;
}
}
代码二:将空间复杂度降到了O(1),用循环去实现trim()函数的功能
class Solution {
public int strToInt(String str) {
if (str == null || str.equals("")) return 0;
int left = 0, ans = 0, flag = 1, check = Integer.MAX_VALUE / 10;
//1.手写一个模块,替代trim(),用来节省O(N)的空间
while (str.charAt(left) == ' ') {
left++;
if (left >= str.length()) return 0; //全为空格
}
if (str.charAt(left) == '-') {
flag = -1;
left++;
} else if (str.charAt(left) == '+') {
left++;
}
for (int i = left; i < str.length(); i++) {
if (str.charAt(i) < '0' || str.charAt(i) > '9') break;
if (ans > check || (ans == check && str.charAt(i) > '7')) return flag == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
ans = ans * 10 + str.charAt(i) - '0';
}
return flag * ans;
}
}
代码三:没看题解之前我自己想的,在IDEA上面能调试通,leetcode上面提交不过
我的想法是先用两个指针,筛选出只包含纯数字的字符串,然后用这个字符串去生成数值。前面两个代码是边检查字符串同时生成数值
class _67 {
int left = 0, right = 0, status = 0;
public int strToInt(String str) {
str = str.trim();
if (str == null || str == "") return 0;
if (str.charAt(0) == '+') {
left = 1;
right = loop(left, str);
} else if (str.charAt(0) == '-') {
left = 1;
status = -1;
right = loop(left, str);
} else if (str.charAt(0) >= '0' && str.charAt(0) <= '9') {
right = loop(left, str);
} else return 0;
return getAns(str.substring(left, right), status);
}
private int loop(int left, String str) {
int i = 0;
for (i = left; i < str.length(); i++) {
if (str.charAt(i) < '0' || str.charAt(i) > '9') break;
}
return i;
}
private int getAns(String str, int status) {
double ans = 0;
for (int i = str.length() - 1; i >= 0; i--) {
ans += (str.charAt(i) - '0') * Math.pow(10, str.length() - 1 - i);
}
if (status == -1) ans = -ans;
if (ans > Math.pow(2, 31) - 1) return new Double(Math.pow(2, 31) - 1).intValue();
if (ans < -Math.pow(2, 31)) return new Double(-Math.pow(2, 31)).intValue();
return new Double(ans).intValue();
}
}
还有一种思路也是先生成数值之后,再去和区间范围比较,这种方法理论上来说更实用,因为我很难记住每一个边界范围的数值。有时间尝试以下: