题目描述:
请你来实现一个
atoi
函数,使其能将字符串转换成整数。首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。
当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。
该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。
注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。
在任何情况下,若函数不能进行有效的转换时,请返回 0。
说明:
假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,qing返回 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、去除左侧空格,判断去除之后的字符串是否为""、"+"、"-",如果是返回0,结束,如果不是,进入第二步
2、获取字符串首位,判断是否为数字或者正负号,如果都不是,返回0,结束,如果是,进入第三步
3、如果是数字,初步判断为正数,后续判断注意首位为0的情况,转5
4、如果不是数字,则说明为"+"/"-",判断第二位是不是数字,如果不是数字,返回0,结束;如果是数字,分别对正数和负数进行判断;对正数判断的时候,删掉首位"+",可调用3中同一方法;对负数进行判断,需要编写新的方法
5、对正数进行判断,首先提取有效字符串,去除字母等,见7,然后将数据转换为int,见8
6、对负数进行判断,可去掉符号位之后调用5中同一方法7进行提取有效字符串,返回之后再将负号连接在字符串左侧,然后将数据转换为int,见8
7、提取有效数据位,可从第一位开始判断,如果为数字,则继续,如果不为数字,则返回当前子串;
8、将数据转换为int,首先,分别对正数和负数去除左侧的0,并返回处理之后的子串;然后分别对正数和负数进行越界判断,首先判断长度,长度相等再判断扣除最后一位(正数是前9位数字,负数是前10位数字大小)剩余的数字和(INT_MAX/10或者INT_MIN/10)比较大小,各减去一位之后不会导致越界,如果相等,则判断最后一位大小。
java代码:
public class Solution8 {
public static void main(String[] args) {
String strInput = "-2147483647";
int intOutput = myAtoi(strInput);
System.out.println(intOutput);
}
// 定义最大int和最小int
public static final int INT_MIN = (int) -Math.pow(2, 31);
public static final int INT_MAX = (int) (Math.pow(2, 31) - 1);
// 对输入字符串进行处理,返回int型结果
public static int myAtoi(String str) {
String strDeleteAheadSpace = str.trim();// 删除字符串中的左侧空格
if (strDeleteAheadSpace.equals("") || strDeleteAheadSpace.equals("-") || strDeleteAheadSpace.equals("+"))
return 0;
String strFirst = strDeleteAheadSpace.substring(0, 1);
if (!isNumberOrMinusOrAdd(strFirst)) {
return 0;
}
if (isNumber(strFirst)) {
return positiveNumber(strDeleteAheadSpace);
}
if (isNumber(strDeleteAheadSpace.substring(1, 2))) {
if (strDeleteAheadSpace.substring(0, 1).equals("+")) {
return positiveNumber(strDeleteAheadSpace.substring(1, strDeleteAheadSpace.length()));
} else {
return negativeNumber(strDeleteAheadSpace);
}
} else {
return 0;
}
}
// 将第一位不是负号的字符串转换为正整数
public static int positiveNumber(String str) {
String strShortNumber = strExtract(str);
return toInt(strShortNumber);
}
// 将带有负号的字符串转换为负整数
public static int negativeNumber(String str) {
String strMinus = str.substring(0, 1);
String strPureNumber = str.substring(1, str.length());
String strShortNumber = strExtract(strPureNumber);
return toInt(strMinus + strShortNumber);
}
// 提取有效的数据位,删除字母等无效位
public static String strExtract(String str) {
StringBuilder strBuf = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
String strPresent = str.substring(i, i + 1);
if (!isNumber(strPresent)) {
break;
}
strBuf.append(strPresent);
}
return strBuf.toString();
}
// 对符合转换int型条件的字符串进行大小判断,并转换为整型,如果不越界,返回整型,如果越界,返回0
public static int toInt(String str) {
str = deleteAheadZero(str);
if (str.equals(""))
return 0;
// 负数,先判断长度,长度大则小,长度小则大,长度等,则判断前11位,和最后一位大小
if (str.substring(0, 1).equals("-")) {
int lenMIN = String.valueOf(INT_MIN).length();
if (str.length() < lenMIN) {
return Integer.parseInt(str);
} else if (str.length() > lenMIN) {
return INT_MIN;
} else {
int intSub = Integer.parseInt(str.substring(0, lenMIN - 1));
if (intSub < INT_MIN / 10) {
return INT_MIN;
} else if (intSub > INT_MIN / 10) {
return Integer.parseInt(str);
} else {
int intLast = Integer.parseInt(str.substring(lenMIN - 1, lenMIN));
int intLastMIN = -(INT_MIN % 10);
if (intLast > intLastMIN) {
return INT_MIN;
} else {
return Integer.parseInt(str);
}
}
}
}
// 正数,先判断长度,长度长则大,长度短则小,长度等则判断前十位大小,如果等,则判断最后一位大小
else {
int lenMAX = String.valueOf(INT_MAX).length();
if (str.length() > lenMAX) {
return INT_MAX;
} else if (str.length() < lenMAX) {
return Integer.parseInt(str);
} else {
int intSub = Integer.parseInt(str.substring(0, lenMAX - 1));
if (intSub > INT_MAX / 10) {
return INT_MAX;
} else if (intSub < INT_MAX / 10) {
return Integer.parseInt(str);
} else {
int intLast = Integer.parseInt(str.substring(lenMAX - 1, lenMAX));
int intLastMAX = INT_MAX % 10;
if (intLast > intLastMAX) {
return INT_MAX;
} else {
return Integer.parseInt(str);
}
}
}
}
}
// 删除数据左侧无效的0,并返回删除之后的字符串
public static String deleteAheadZero(String str) {
// 负数,从前往后检索,如果不为零,则返回该位置到结束位置的字符串
// 如果一直为零,循环结束之后i为length,则返回""
if (str.substring(0, 1).equals("-")) {
str = str.substring(1, str.length());
for (int i = 0; i < str.length(); i++) {
if (!str.substring(i, i + 1).equals("0")) {
return "-" + str.substring(i, str.length());
}
}
return "";
}
// 正数,从前往后检索,如果不为零,则返回该位置到结束位置的字符串
// 如果一直为零,循环结束之后i为length,则返回""
else {
for (int i = 0; i < str.length(); i++) {
if (!str.substring(i, i + 1).equals("0")) {
return str.substring(i, str.length());
}
}
return "";
}
}
// 判断是否为数字,正则表达式
public static boolean isNumber(String strFirst) {
String regex = "\\d";
if (strFirst.matches(regex))
return true;
return false;
}
// 判断是否为数字或者正负号
public static boolean isNumberOrMinusOrAdd(String strFirst) {
String regex = "[\\d[\\-][\\+]]";
if (strFirst.matches(regex))
return true;
return false;
}
}
总结:
这道题难度一般,不涉及较复杂的算法,但是需要判断的边界太多,想要完全AC,需要非常细心,思路清晰。