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