Leetcode剑指Offer刷题指南:
解法:模拟
class Solution {
public boolean isNumber(String s) {
if (s == null || s.length() == 0) return false;
//去掉首位空格
s = s.trim();
boolean numFlag = false;
boolean dotFlag = false;
boolean eFlag = false;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) >= '0' && s.charAt(i) <= '9') {
//判定为数字,则标记numFlag
numFlag = true;
} else if (s.charAt(i) == '.' && !dotFlag && !eFlag) {
//判定为. 需要没出现过.并且没出现过e
dotFlag = true;
} else if ((s.charAt(i) == 'e' || s.charAt(i) == 'E') && !eFlag && numFlag) {
//判定为e,需要没出现过e,并且出过数字了
eFlag = true;
numFlag = false;//为了避免123e这种请求,出现e之后就标志为false
} else if ((s.charAt(i) == '+' || s.charAt(i) == '-') && (i == 0 || s.charAt(i - 1) == 'e' || s.charAt(i - 1) == 'E')) {
//判定为+-符号,只能出现在第一位或者紧接e后面
} else {
return false;
}
}
return numFlag;
}
}
解法:模拟
class Solution {
public int strToInt(String str) {
char[] c = str.trim().toCharArray();
if (c.length == 0) return 0;
int ret = 0, max = Integer.MAX_VALUE / 10;
int i = 1, sign = 1;
if (c[0] == '-') sign = -1;
else if (c[0] != '+') i = 0;
for (; i < c.length; i++) {
if (c[i] < '0' || c[i] > '9') break;
if (ret > max || ret == max && c[i] > '7') {
//在每轮数字拼接前,判断 ret 在此轮拼接后是否超过 2147483647 ,若超过则加上符号位直接返回
return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
ret = ret * 10 + (c[i] - '0');
}
return sign * ret;
}
}
关于以下越界处理的解释:
if (ret > max || (ret == max && c[i] > '7')) {
//在每轮数字拼接前,判断 ret 在此轮拼接后是否超过 2147483647 ,若超过则加上符号位直接返回
return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
如果直接向 int 变量赋值 -2147483648 系统会报错,虽然理论上确实可以取到,但是直接赋值不行
即 INT_MIN 明明是 -2147483648 ,但是为什么却只需要判断当前字符是否大于 7 ,因为按常理来说当符号为负时 str.charAt(i) 为 '8' 也是不越界的,但是为什么这里只判断 ‘7’ 呢?
这是因为我们如果直接向一个 int 变量赋值 -2147483648 ,系统是会报错的
如果想要返回这个数那就需要使用 INT_MIN ,因为 INT_MIN = -2147483648 。
那么我们回过头来看这题,考虑字符串为“-2147483648”这种情况,即 res == 214748364 的前提下,(2147483648)的当前字符是 ‘8’ ,那么按照最常规的思路,这个数是在 int 的取值范围中,那么我要存放它,但是 int 变量并不能直接存放这个数,因此我要找一个与 -2147483648 相等的,可以表示它的数,那就是 INT_MIN 。因此即使符号是负号,我们仍然可以将判断条件写为 str.charAt(j) > '7' ,因为当取 ‘8’ 时我们返回的也是 INT_MIN 。