LeetCode第八题 字符串转换整数(atoi)(java)

题目描述:

请你来实现一个 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,需要非常细心,思路清晰。

猜你喜欢

转载自blog.csdn.net/lizehao1973/article/details/86290983