LeetCode.8-字符串轉整數(String to Integer (atoi))

這是悅樂書的第349次更新,第374篇原創

java

01 看題和準備

今天介紹的是LeetCode算法題中Medium級別的第4題(順位題號是8)。實現將字符串轉換爲整數的atoi方法。git

該函數首先去掉所需丟棄的空白字符,直到找到第一個非空白字符。而後,從該字符開始,採用可選的初始加號或減號,後跟儘量多的數字,並將它們轉換爲整數。算法

字符串能夠包含在造成整數以後的其餘字符,這些字符將被忽略而且對此函數的行爲沒有影響。數據結構

若是str中的第一個非空白字符不是有效的整數,或者因爲str是空的或者只包含空白字符而不存在這樣的序列,則不執行轉換。函數

若是沒法執行有效轉換,則返回零值。優化

注意code

  • 只有空格字符' '被視爲空格字符。

假設咱們正在處理一個只能在32位有符號整數範圍內存儲整數的環境:[ -2^31,2^31 -1]。若是數值超出可表示值的範圍,則返回INT_MAX(2^31-1)或INT_MIN(-2^31)。例如:內存

輸入:「42」
輸出:42字符串

輸入:「 -42」
輸出:-42
說明:第一個非空白字符是' - ',這是減號。而後取儘量多的數字,獲得42。string

輸入:「4193 with words」
輸出:4193
說明:轉換在數字「3」處中止,由於下一個字符不是數字。

輸入:「words and 987」
輸出:0
說明:第一個非空白字符是'w',它不是數字或+/-符號。所以,沒法執行有效轉換。

輸入:「-91283472332」
輸出:-2147483648
說明:數字「-91283472332」超出32位有符號整數的範圍。返回INT_MIN(-2^31)。

02 第一種解法

將字符串轉成整數,根據題目給的說明和試錯,須要考慮如下幾個條件:

  • 是否爲空,或者由空格組成。

  • 是否帶有正負符號,正號能夠忽略,負號在返回結果時須要帶上。

  • 以0開頭,須要跳過連續的前置0。例如"000123",轉換的結果是123。

  • 超過了Integer的最大邊界或最小邊界。

  • 小數點能夠忽略,由於是轉成整型,會舍掉小數點後面的數。

  • 出現多個正負符號,直接返回0。例如"+-2",結果是0。

  • 第一位只能是數字(0到9)或者正負符號,出現其餘字符直接返回0。

根據上面這些狀況,在關鍵處進行判斷便可。

public int myAtoi(String str) {
    str = str.trim();
    // 判空
    if (str.length() < 1) {
        return 0;
    }
    // 判斷首位字符
    char c = str.charAt(0);
    if (!Character.isDigit(c) && c != '-' && c != '+') {
        return 0;        
    }
    // 判斷符號
    boolean flag = false;
    if (c == '-') {
        flag = true;
    }
    int end = 0;
    for (int i=1; i<str.length(); i++) {
        if (Character.isDigit(str.charAt(i))) {
            end = i;    
        } else {
            break;
        }
    }
    String newStr = str.substring(flag ? 1 : 0, end+1);
    if (newStr.length() < 1 || newStr.equals("+")) {
        return 0;
    }
    // 判斷邊界
    if (!newStr.startsWith("0") && newStr.length() > 12) {
        return flag ? Integer.MIN_VALUE : Integer.MAX_VALUE;
    }
    Long result = Long.parseLong(newStr);
    if (result.toString().length() > 11) {
        return flag ? Integer.MIN_VALUE : Integer.MAX_VALUE;
    }
    if (result > Integer.MAX_VALUE) {
        return flag ? Integer.MIN_VALUE : Integer.MAX_VALUE;
    }
    return flag ? 0-(int)result.longValue() : (int)result.longValue();
}


03 第二種解法

在第一種解法的基礎上,咱們還能夠作下優化。

public int myAtoi2(String str) {
    if (str == null) {
        return 0;
    }
    str = str.trim();
    if (str.isEmpty()) {
        return 0;
    }
    char c = str.charAt(0);
    int start = 0;
    if (c == '+' || c == '-') {
        start = 1;
    }
    int end = str.length(), n = str.length();
    for (int i=start; i<n; i++) {
        char ch = str.charAt(i);
        if ("0123456789".indexOf(ch) < 0) {
            end = i;
            break;
        } else {
            // 截取的字符串長度可能會超過Integer的邊界
            if (i >= 10) {
                long tem = Long.valueOf(str.substring(0, i+1));
                if (tem > Integer.MAX_VALUE) {
                    return Integer.MAX_VALUE;
                } else if (tem < Integer.MIN_VALUE) {
                    return Integer.MIN_VALUE;
                }
            }
        }
    }
    if (end <= start) {
        return 0;
    }
    long result = Long.valueOf(str.substring(0, end));
    if (result > Integer.MAX_VALUE) {
        return Integer.MAX_VALUE;
    } else if (result < Integer.MIN_VALUE) {
        return Integer.MIN_VALUE;
    }
    return (int)result;
}


04 第三種解法

咱們也能夠不採用截取字符串的方式,經過計算每一位數,判斷是不是0到9的數字,而且判斷是否越界。

public int myAtoi3(String str) {
    if (str == null) {
        return 0;
    }
    str = str.trim();
    if (str.isEmpty()) {
        return 0;
    }
    int index = 0, total = 0, n = str.length();
    int sign = 1;
    // 判斷正負
    // 只判斷一次,不能使用循環
    if (index < n && (str.charAt(index) == '+' 
            || str.charAt(index) == '-')) {
        sign = str.charAt(index) == '-' ? -1 : 1;
        index++;
    }
    // 計算整數
    while (index < n) {
        int num = str.charAt(index)-'0';
        if (num < 0 || num > 9) {
            break;
        }
        // 避免越界
        if (total > Integer.MAX_VALUE/10 || 
                (total == Integer.MAX_VALUE/10 
                && num > Integer.MAX_VALUE%10)) {
            return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
        }
        total = total*10 + num;
        index++;
    }
    return total*sign;
}


05 小結

算法專題目前已連續日更超過六個月,算法題文章217+篇,公衆號對話框回覆【數據結構與算法】、【算法】、【數據結構】中的任一關鍵詞,獲取系列文章合集。

以上就是所有內容,若是你們有什麼好的解法思路、建議或者其餘問題,能夠下方留言交流,點贊、留言、轉發就是對我最大的回報和支持!

相關文章
相關標籤/搜索