GitHub:https://github.com/biezhihua/LeetCode
题目
实现 atoi
,将字符串转为整数。
提示:仔细考虑所有输入情况。如果你想挑战自己,请不要看下面并自己考虑所有可能的输入情况。
说明:这题解释的比较模糊(即没有指定输入格式)。你得事先汇集所有的输入情况。
atoi的要求:
- 这个函数需要丢弃之前的空白字符,直到找到第一个非空白字符。之后从这个字符开始,选取一个可选的正号或负号后面跟随尽可能多的数字,并将其解释为数字的值。
- 字符串可以在形成整数的字符后包括多余的字符,将这些字符忽略,这些字符对于函数的行为没有影响。
- 如果字符串中的第一个非空白的字符不是有效的整数,或者没有这样的序列存在,字符串为空或者只包含空白字符则不进行转换。
- 如果不能执行有效的转换,则返回 0。如果正确的值超过的可表示的范围,则返回 INT_MAX(2147483647)或 INT_MIN(-2147483648)。
解法
我自己并没有完全解出来这道题目,原因是没有测试覆盖所有的情况。
正如题目中提示的一样,这道题目真正的难点在于如何将所有可能输入的情况覆盖到。
除了要考虑到:
- 任意地方的空白字符
‘ ’
- 跳过任意地方的非数字字符
- 数值范围限制(INT_MAX or INT_MIN)
我们还需要做到:
- 标记出正负
- 剔除空白字符
- 判断数值大小是否超过范围
- 非法输入
那么也就随之而来了:
public static int myAtoi(String str) {
// 合法性判断
if (str.isEmpty()) return 0;
// 正负号标记
int sign = 1;
// 转换值
int base = 0;
// 索引位数
int i = 0;
// 剔除开始空白字符
while (str.charAt(i) == ' ')
i++;
// 判断正负号
if (str.charAt(i) == '-' || str.charAt(i) == '+')
sign = str.charAt(i++) == '-' ? -1 : 1;
// 索引有效数字字符
while (i < str.length() && str.charAt(i) >= '0' && str.charAt(i) <= '9') {
// that statement is used to test if the num is bigger than INT_MAX after the str[i] is handled, if base > INT_MAX/10,
// then base10+ str[i] -‘0’> base10>INT_MAX, or when base== INT_MAX/10, that means all the places are the same as INT_MAX except the ones place, so str[i]>‘7’ is needed.
// 上面这段是LeetCode国外站对下面代码的解释。
// 简单来说就是
// 如果`base > MAX_VALUE/10`,那么`base*10 + new_value` > `base*10` > `MAX_VALUE`。这个应该很容易理解,这种情况下就会发生溢出。
// 若`base == INT_MAX/10`,而且`new_value = str.charAt(i++) - '0'`大于`7`,也会发生溢出。因为`MAX_VALUE = 2147483647`
if (base > Integer.MAX_VALUE / 10 || (base == Integer.MAX_VALUE / 10 && str.charAt(i) - '0' > 7)) {
return (sign == 1) ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
// 计算转换值
base = 10 * base + (str.charAt(i++) - '0');
}
// 计算结果值
return base * sign;
}
引用:
1. https://leetcode.com/problems/string-to-integer-atoi/discuss/4654/My-simple-solution