1 算法描述
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:
读入字符串并丢弃无用的前导空格
检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
返回整数作为最终结果。
注意:
本题中的空白字符只包括空格字符 ' ' 。
除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
示例 1:
输入:s = "42"
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
第 1 步:"42"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"42"(读入 "42")
^
解析得到整数 42 。
由于 "42" 在范围 [-231, 231 - 1] 内,最终结果为 42 。
示例 2:
输入:s = " -42"
输出:-42
解释:
第 1 步:" -42"(读入前导空格,但忽视掉)
^
第 2 步:" -42"(读入 '-' 字符,所以结果应该是负数)
^
第 3 步:" -42"(读入 "42")
^
解析得到整数 -42 。
由于 "-42" 在范围 [-231, 231 - 1] 内,最终结果为 -42 。
示例 3:
输入:s = "4193 with words"
输出:4193
解释:
第 1 步:"4193 with words"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"4193 with words"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"4193 with words"(读入 "4193";由于下一个字符不是一个数字,所以读入停止)
^
解析得到整数 4193 。
由于 "4193" 在范围 [-231, 231 - 1] 内,最终结果为 4193 。
示例 4:
输入:s = "words and 987"
输出:0
解释:
第 1 步:"words and 987"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"words and 987"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"words and 987"(由于当前字符 'w' 不是一个数字,所以读入停止)
^
解析得到整数 0 ,因为没有读入任何数字。
由于 0 在范围 [-231, 231 - 1] 内,最终结果为 0 。
示例 5:
输入:s = "-91283472332"
输出:-2147483648
解释:
第 1 步:"-91283472332"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"-91283472332"(读入 '-' 字符,所以结果应该是负数)
^
第 3 步:"-91283472332"(读入 "91283472332")
^
解析得到整数 -91283472332 。
由于 -91283472332 小于范围 [-231, 231 - 1] 的下界,最终结果被截断为 -231 = -2147483648 。
提示:
0 <= s.length <= 200
s 由英文字母(大写和小写)、数字(0-9)、' '、'+'、'-' 和 '.' 组成
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/string-to-integer-atoi
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
2 解题思路
字符串转换整数可以分三步来处理:
第一步:去除前置空格;
第二步:处理符号位;符号的处理可以使用 +1和-1来处理,正数不用处理,负数就乘以-1。
第三步:从左向右遍历字符;遍历的过程中要进行几个判断:
1)判断是否为数字,如果不是数字就跳出遍历;
2)判断是否超出最大值和最小值,超出的按照题目要求返回对应的值。
最大值和最小值计算公式:
假设 num 是最终的值,tmp 是遍历得到的值,max是int型最大值,min是int型最小值。那么有公式:
min <= num*10 + tmp <= max
转换得到:min/10 - tmp/10 <= num <= max/10 - tmp/10
计算机的除法是没有余数的,所以可以简化为:min/10 <= num <= max/10
可以分为两种情况 大于 和 等于。以num>=min/10为例,
如果num<min/10,肯定是会溢出的。但是如果num=min/10 = -2147483648/10 = -214748364。
如果tmp 的值小于-8,还是会溢出,所以小于最小值的判断条件为:
num<(min/10) || (num==min/10 && tmp<min%10)
大于最大值的判断条件为:
num>(max/10) || (num==min/10 && tmp>max%10)
编码如下所示:
public int myAtoi(String s) {
char[] chs = s.toCharArray();//字符串转化为字符数组
int idx = 0;//字符串数组下标
int sign = 1;//正负标识
int num = 0;//目标数值
//第一步:去除空格
while(idx<chs.length && chs[idx]==' '){
idx++;
}
//如果全是空格返回0
if(idx>=chs.length){
return 0;
}
//第二步:正负处理
if(chs[idx] == '-'){
sign = -1;
idx++;
} else if(chs[idx] == '+'){
idx++;
}
//第三步:遍历字符数组
while(idx<chs.length){
if(chs[idx]>='0' && chs[idx]<='9'){//判断是否为数值
int tmp = Character.getNumericValue(chs[idx])*sign;//字符转化为带符号的数值
if((num<Integer.MIN_VALUE/10) || (num==Integer.MIN_VALUE/10 && tmp<Integer.MIN_VALUE%10)){//小于最小值处理
num = Integer.MIN_VALUE;
break;
} else if((num>Integer.MAX_VALUE/10) || (num==Integer.MAX_VALUE/10 && tmp>Integer.MAX_VALUE%10)){//大于最大值处理
num = Integer.MAX_VALUE;
break;
} else{
num = num*10 + tmp;
}
idx++;
} else{
break;
}
}
return num;
}