題目描述
請你來實現一個 atoi 函數,使其能將字符串轉換成整數。
首先,該函數會根據需要丟棄無用的開頭空格字符,直到尋找到第一個非空格的字符爲止。接下來的轉化規則如下:
如果第一個非空字符爲正或者負號時,則將該符號與之後面儘可能多的連續數字字符組合起來,形成一個有符號整數。
假如第一個非空字符是數字,則直接將其與之後連續的數字字符組合起來,形成一個整數。
該字符串在有效的整數部分之後也可能會存在多餘的字符,那麼這些字符可以被忽略,它們對函數不應該造成影響。
注意:假如該字符串中的第一個非空格字符不是一個有效整數字符、字符串爲空或字符串僅包含空白字符時,則你的函數不需要進行轉換,即無法進行有效轉換。
在任何情況下,若函數不能進行有效的轉換時,請返回 0 。
提示:
- 本題中的空白字符只包括空格字符 ’ ’ 。
- 假設我們的環境只能存儲 32 位大小的有符號整數,那麼其數值範圍爲 [−2^31, 2^31 − 1]。如果數值超過這個範圍,請返回 INT_MAX (2^31 − 1) 或 INT_MIN (−2^31) 。
思路分析
題目很清晰地給出了轉化規則,我們需要將其轉化爲代碼。
- trim() 將字符串首部的空格去除;
- 判斷第一個字符:
- 爲 ‘-’ 則將標誌位置爲 -1 ,從第二位開始算;
- 爲 ‘+’ 則將標誌位置爲 1 ,從第二位開始算;
- 爲除數字 0-9 外的字符直接返回。
- 主要問題在 int 的邊界問題上。
- 最小負數
- int的最大正數的絕對值小於最小負數絕對值。我們需要讓符號位也參與運算過程,避免最後置負時超出邊界。’+’ => 1;’-’=> -1。
- 數值越界
- 在每次循環時,通過INT_MAX/10的值提前判斷是否越界。
- value > INT_MAX/10 時,說明擴大10倍後,value 必將越界。
- 當 value == INT_MAX/10 時,說明擴大10倍後,value 可能越界,也可能不越界,需要利用當前的加數 digit 做進一步的判斷:正數是當 digit > 7 時,越界;複數是當 digit > 8 時,越界。
- 當 value < INT_MAX/10 時,本輪循環必不越界。
- 正負數越界判斷合併
- 將-1、1轉換爲0、1 => (isNegative + 1) / 2 + digit > 8時,數值越界。
- 最小負數
綜上所述,
overValue = isNegative * value - INT_MAX/10
+ (((isNegative+1)/2 + digit > 8) ? 1:0);
當overValue>0時,數值將會越界,反之不會。
代碼實現
public static int myAtoi(String str) {
if(str==null||str.length()==0){
return 0;
}
str = str.trim();
if(str==null||str.length()==0){
return 0;
}
int isSub = 1;
int sum = 0,overvalue = 0,digit = 0,index = 0;
if (str.charAt(0) == '-') {
isSub = -1;
index = 1;
} else if (str.charAt(0) == '+') {
isSub = 1;
index = 1;
} else if (str.charAt(0) > '9' || str.charAt(0) < '0') {
return 0;
}
for (int i = index; i <= str.length() - 1; i++) {
digit = str.charAt(i) - '0';
overvalue = isSub * sum - Integer.MAX_VALUE / 10 + (((isSub + 1) / 2 + digit > 8) ? 1 : 0);
if ((digit < 0 || digit > 9)) {
break;
} else if (overvalue > 0) {
return isSub == -1 ? Integer.MIN_VALUE : Integer.MAX_VALUE;
}
sum = sum * 10 + isSub * digit;
}
return sum;
}