1. 程式人生 > >LeetCode第八題 字串轉換整數(atoi)(java)

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,需要非常細心,思路清晰。