力扣 - 劍指 Offer 67. 把字串轉換成整數

linzeliang發表於2021-11-05

題目

劍指 Offer 67. 把字串轉換成整數

思路1

  • 根據題意,要解決這題,首先要判斷的條件有:
    • 不包括首位空格
    • 第一位必須為:+-、數字三者其一,否則不合法
    • 數字必須連續的,如果遇到非數字,結束判斷
    • 判斷結果要在 \(-2^{31}\)~\((2^{31}-1)\) 之間,如果超過的話,就輸出最大值 / 最小值
  • 我們用sign記錄符號、res記錄每次遍歷累加的值、threshold記錄閾值(我們閾值取Integer.MAX_VALUE/10,即小了一位數,作用後面再說)、index記錄開始的索引。接下來開始解析:
    • 首先,我們使用Java的trim方法去除首位空格
    • 然後判斷第一位的字元是什麼,為負號sign就為-1,預設是正號1。同時還要設定開始比遍歷的索引index,如果為負號或者顯示的正號,我們就設定為1(因為這兩個符號都佔了一個位置),否則就預設從0開始(這時候不用管是否為數字,這個判斷留到下面再去判斷)
    • 接下來根據前面設定的index,從index開始遍歷字串,判斷每一位字元:
      • 如果不為數字則跳出迴圈;
      • 如果res結果大於閾值res還沒加上當前值,因為如果res已經大於閾值了,不管當前值是多大也沒有影響)則說明拼接後的值已經超過了Integer.MAX_VALUE,需要返回整數的最大值;
      • 如果res == threshold,且當前的值也大於7(為什麼要大於7呢,因為大於7就說明大於正整數的最大值,前幾位一樣,那麼就比較最後一位嘛),此時再根據符號,直接返回最大值即可。
      • (注意:因為最大正整數和最小負整數不僅僅是符號不一樣的區別,將最小負整數去掉符號之後,還是比最大正整數的值還大1。所以這個是如何保證能正確判斷呢?主要是在cs[i] > '7'這個地方:這個條件判斷了如果res等於最大正整數,此時不是直接返回最大正整數,而是進行拼接,進行下一輪判斷,當然,如果是負數的話,達到-2147483647也是進行拼接,如果是-2147483648,那麼就會直接返回最大負整數,這也就是為什麼c[i]要大於7而不是大於等於‘7了)
    • 如果上一步都沒超最大值,此時講當前值拼接到res中即可:res = res*10 + (cs[i] - '0');
    • 最後返回res*sign,由sign控制符號

程式碼

class Solution {
    public int strToInt(String str) {
        char[] cs = str.trim().toCharArray();

        // 非空格的字元長度為0,直接返回0
        if (cs.length == 0) {
            return 0;
        }

        // 符號標誌,代表正負號,預設為正
        int sign = 1;
        // 儲存結果
        int res = 0;
        // 預設第一位是符號,所以從第二位開始計算,即1
        int index = 1;
        // 閾值
        int threshold = Integer.MAX_VALUE / 10;

        // 判斷第一位非空格的的字元
        if (cs[0] == '-') {
            // 負號
            sign = -1;
        } else if (cs[0] != '+') {
            // 如果不是正號的話,我們先預設:第一位是數字、為正數,下面再進行判斷
            index = 0;
        }

        // 根據前面的index判斷是從第0位還是第1位開始判斷
        for (int i = index; i < cs.length; i++) {
            // 不是數字就直接結束
            if (cs[i] < '0' || cs[i] > '9') {
                break;
            }

            // 超出範圍
            if (res > threshold || (res == threshold && cs[i] > '7')) {
                return sign == 1 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
            }
            // 進行拼接
            res = res*10 + (cs[i] - '0');
        }
        
        return sign * res;

    }
}

複雜度分析

  • 時間複雜度:\(O(N)\),線性遍歷陣列所需時間為\(O(N)\)
  • 空間複雜度:\(O(N)\),將字串轉換成字元陣列所佔用的空間

相關文章