算法题之输出字符串的数字
题目描述
请你来实现一个 atoi 函数,使其能将字符串转换成整数。
首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。接下来的转化规则如下:
如果第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字字符组合起来,形成一个有符号整数。
假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成一个整数。
该字符串在有效的整数部分之后也可能会存在多余的字符,那么这些字符可以被忽略,它们对函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换,即无法进行有效转换。在任何情况下,若函数不能进行有效的转换时,请返回 0 。
提示:
本题中的空白字符只包括空格字符 ’ ‘ 。
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,请返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。
示例 1:
输入: "42“
输出: 42
示例 2:
输入: " -42“
输出: -42
解释: 第一个非空白字符为 ‘-’, 它是一个负号。
我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。
示例 3:输入: "4193 with words“
输出: 4193
解释: 转换截止于数字 ‘3’ ,因为它的下一个字符不为数字。
示例 4:输入: "words and 987“
输出: 0解释: 第一个非空字符是 ‘w’, 但它不是数字或正、负号。
因此无法执行有效的转换。
示例 5:输入: "-91283472332“
输出: -2147483648
解释: 数字 “-91283472332” 超过 32 位有符号整数范围。
因此返回 INT_MIN (−231) 。
题解分析
思路:
1.首先将字符串去掉首尾的空格,转换成字符数组
2.判断第一个字符是’+‘还是’-’,或者直接是字符,从而进行正负号的初始化,以及确定字符数组遍历的起始索引时0还是1
3.遍历该字符数组:
3.1如果当前遍历的字符不是数字,直接退出while循环
3.2如果当前遍历的字符是数字,则需要之前的总和已经当前值进行联合判断:
(1)如果当前添加arr[i]时,之前的数值已经超过了214748364,则无论arr[i]为0~9中的哪个数值,num = num * 10 + (arr[i] - ‘0’)的结果都会大于2147483647
(2)或者当前添加arr[i]时,之前的数值已等于214748364,但是arr[i]超过了7,则num = num * 10 + (arr[i] - ‘0’)的结果亦是2147483648和2147483649,也大于2147483647
(3)上面两者情况:需要根据符号位返回Integer.MAX_VALUE或者Integer.MIN_VALUE
3.3如果都不满足,说明可以继续扫描下一个字符,并把当前值作为个位进行求和运算:num = num * 10 + (arr[i] - ‘0’)
4.最后退出while循环即可以找到存在的数值:符号位(symbol) * 数值(num)
图解
代码实现
public class FindNumInString {
public static void main(String[] args) {
String str = " -91283472332 java ";
FindNumInString solution = new FindNumInString();
int res = solution.strToInt(str);
System.out.println("该字符串" + str + "中的找到的数字为:" + res);
}
//在String字符串中找到满足要求的整数,并将其输出
public int strToInt(String str) {
//首先我们需要利用String字符串的trim()方法:去掉首尾的不必要的空格
char[] arr = str.trim().toCharArray();
int symbol = 1;//初始化为正数
int index = 1;//字符串数组开始遍历的起始索引
int num = 0;//初始化接收的String字符串中的int数值
int maxValue = Integer.MAX_VALUE;
int minValue = Integer.MIN_VALUE;
int cmpValue = maxValue / 10;
if (arr.length == 0) {
//说明字符串没有值
return 0;
}
//设置符号值和初始遍历索引
if (arr[0] == '-') {
//若第一位是负号的话,将symbol置为1
symbol = -1;
}else if (arr[0] != '+') {
//表示第一位即为数值或者是其他字符,将index从1-->0,即从0开始遍历
index = 0;
}
for (int i = index; i < arr.length; i++) {
if (arr[i] < '0' || arr[i] > '9') {
//说明该字符不为数字,直接退出循环
break;
}
if (num > cmpValue || num == cmpValue && arr[i] > '7') {
//如果当前添加arr[i]时,之前的数值已经超过了214748364,则无论arr[i]为0~9中的哪个数值,num = num * 10 + (arr[i] - '0')的结果都会大于2147483647
//或者当前添加arr[i]时,之前的数值已等于214748364,但是arr[i]超过了7,则num = num * 10 + (arr[i] - '0')的结果亦是2147483648和2147483649,也大于2147483647
//2.若匹配到最后越界,则返回maxValue或者minValue
return symbol == 1 ? maxValue : minValue;
}
//如果不满足上述条件
num = num * 10 + (arr[i] - '0');//将num的值进行更新操作
}
//退出while循环,此时num的值即为输出的值
//1.若匹配到一个非数字字符情况break退出while
//1.1 第一个即为非数字字符:此时num为初始设置值0
//1.2 后续退出:num即为不加正负号之前的结果
return symbol * num;
}
}