【每日算法Day 89】手動實現字符串轉整數(atoi)函數,你會嗎?

v2-1f4c1b27038f92b4a9e65bae4a3d3701_b.jpg
還有幾個小時ACL2020就出結果了,祈禱!

題目鏈接

LeetCode 字符串轉換整數(atoi)[1]

題目描述

請你來實現一個 atoi 函數,使其能將字符串轉換成整數。

首先,該函數會根據需要丟棄無用的開頭空格字符,直到尋找到第一個非空格的字符爲止。接下來的轉化規則如下:

  • 如果第一個非空字符爲正或者負號時,則將該符號與之後面儘可能多的連續數字字符組合起來,形成一個有符號整數。
  • 假如第一個非空字符是數字,則直接將其與之後連續的數字字符組合起來,形成一個整數。
  • 該字符串在有效的整數部分之後也可能會存在多餘的字符,那麼這些字符可以被忽略,它們對函數不應該造成影響。

注意:假如該字符串中的第一個非空格字符不是一個有效整數字符、字符串爲空或字符串僅包含空白字符時,則你的函數不需要進行轉換,即無法進行有效轉換。

在任何情況下,若函數不能進行有效的轉換時,請返回 0

說明:

  • 本題中的空白字符只包括空格字符 ' ' 。
  • 假設我們的環境只能存儲 32 位大小的有符號整數,那麼其數值範圍爲 [−2^{31},  2^{31} − 1]。如果數值超過這個範圍,請返回 INT_MAX2^{31} − 1) 或 INT_MIN−2^{31}) 。

示例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) 。
      

題解

官方題解用的有限狀態自動機,理解起來也是比較輕鬆的,寫起來也避免了一堆臃腫的 if-else 。但是我這裏就不用自動機了,直接模擬就行了,寫起來也很輕鬆好理解!

  • 首先用一個變量 idx 標記當前遍歷到的位置,用 sign = 1, -1 表示整數的正負性。
  • 然後從 idx = 0 開始,將開頭的空格全部去掉。
  • 然後判斷當前的位置 idx 處的字符是不是 +, - 或者數字,並且 idx 要小於字符串長度。如果一個都沒滿足,那麼說明是非法字符串,直接返回 0
  • 然後如果當前的位置 idx 處的字符是 - ,那麼就令 sign = -1 。否則如果是 + ,就令 sign = 1 。然後遍歷後一個字符。
  • 最後遍歷一段連續的數字,把它轉換成整數,注意轉換的時候要乘上符號位 sign 。如果發現數字超過了 [INT_MIN, INT_MAX] 範圍,就直接返回最大最小值就行了。
  • 否則的話最後就是合法整數,直接返回答案。

代碼

c++

        class Solution {
public:
    int myAtoi(string str) {
        int idx = 0, n = str.size();
        long res = 0, sign = 1;
        while (idx < n && str[idx] == ' ') idx++;
        if (idx >= n || (str[idx] != '+' && str[idx] != '-' && !isdigit(str[idx]))) return 0;
        if (str[idx] == '-') {
            sign = -1;
            idx++;
        } else if (str[idx] == '+') {
            idx++;
        }
        while (idx < n && isdigit(str[idx])) {
            res = res*10+sign*(str[idx++]-'0');
            if (res > INT_MAX) return INT_MAX;
            if (res < INT_MIN) return INT_MIN;
        }
        return res;
    }
};

      

python

        class Solution:
    def myAtoi(self, str: str) -> int:
        str = str.lstrip()
        n, idx = len(str), 0
        res, sign = 0, 1
        if idx >= n or (str[idx] != '+' and str[idx] != '-' and not str[idx].isdigit()): return 0
        if str[idx] == '-':
            sign = -1
            idx += 1
        elif str[idx] == '+':
            idx += 1
        for c in str[idx:]:
            if not c.isdigit(): break
            res = res*10+sign*(int(c))
            if res > 2**31-1: return 2**31-1
            if res < -2**31: return -2**31
        return res

      

正則表達式(python)

        class Solution:
    def myAtoi(self, str: str) -> int:
        return max(min(int(*re.findall('^[\+\-]?\d+', str.lstrip())), 2**31-1), -2**31)

      

參考資料

[1]

LeetCode 字符串轉換整數(atoi): leetcode-cn.com/problem

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章