LeetCode 字符串轉換整數 (atoi)

字符串轉換整數 (atoi)


題目來源:https://leetcode-cn.com/problems/string-to-integer-atoipython

題目


實現一個 atoi 函數,使其能將字符串轉換成整數。正則表達式

首先,該函數會根據須要丟棄無用的開頭空格字符,直到尋找到第一個非空格的字符爲止。segmentfault

當咱們尋找到的第一個非空字符爲正或者負號時,則將該符號與以後面儘量多的連續數字組合起來,做爲該整數的正負號;假如第一個非空字符是數字,則直接將其與以後連續的數字字符組合起來,造成整數。bash

該字符串除了有效的整數部分以後也可能會存在多餘的字符,這些字符能夠被忽略,它們對於函數不該該形成影響。微信

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

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

說明:.net

假設咱們的環境只能存儲 32 位大小的有符號整數,那麼其數值範圍爲 [−231, 231 − 1]。若是數值超過這個範圍,請返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。code

示例 1:blog

輸入: "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. 首先去除前面的空格(這裏不用 lstrip() 函數,避免產生新的變量,直接定位不爲空格的字符索引);
  2. 定位不爲空格的索引後,今後處開始判斷第一個字符爲 +- 的狀況。定義 sign,初始化爲 1 表示正數,如果遇到 - 則修改成 -1,表示負數
  3. 判斷是否爲數字,直接用 ASCII 碼數值進行比較;
  4. +- 字符的狀況下,判斷第一個字符不爲數字直接跳出循環;
  5. 判斷數值是否會越界,如果越界,則跳出循環。

其中越界這部分的內容能夠參考下面的文章:

Python 整數反轉

上面的文章中大體說起了越界的狀況,這裏的處理大同小異。只是這裏遍歷的字符不一樣於負數取模,處理最小值邊界的狀況下要注意。

代碼實現


class Solution:
    def myAtoi(self, str: str) -> int:
        # max_value_div_10 = (1<<31) // 10
        # min_value_div_10 = -(-((1<<31)-1) // -10)
        INT_MAX = (1<<31) - 1
        INT_MIN = -(1<<31)

        str_len = len(str)
        # 去除空格,這裏不使用 lstrip() 避免產生新的遍歷
        # 直接定位不爲空格的字符索引
        index = 0
        while index < str_len:
            if str[index] != ' ':
                break
            index += 1

        # 若是索引值就等於字符長度,直接返回 0
        if index == str_len:
            return 0

        # 判斷取出空格後首位字符,判斷合法,記錄正負
        sign = 1
        first_chr = str[index]
        if first_chr == '+':
            index += 1
            sign = 1
        elif first_chr == '-':
            index += 1
            sign = -1

        res = 0

        while index < str_len:
            cur_chr = str[index]

            if cur_chr > '9' or cur_chr < '0':
                break
            
            cur_chr = int(cur_chr)
            # 判斷是否越界
            if res > INT_MAX // 10 or (res == INT_MAX // 10 and cur_chr > 7):
                return INT_MAX
            # 這裏處理邊界有些不一樣,與上面說起的文章比較,須要注意
            if res < -(INT_MIN // -10) or (res == -(INT_MIN // -10) and cur_chr > 8):
                return INT_MIN
            

            # 每一步都把符號位乘進去
            res = res * 10 + sign * cur_chr
            index += 1
        

        return res

實現結果


實現結果

擴展部分


這裏說起一個比較騷的解法。除了導入必要庫,使用正則表達式一行代碼就解決了該問題。來源出自下面這位做者的題解:

https://leetcode-cn.com/problems/string-to-integer-atoi/solution/python-1xing-zheng-ze-biao-da-shi-by-knifezhu/

大體是這樣的:

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

這裏 max(min(數字,2**31 - 1), -2**31) 處理邊界問題,re.findall() 這裏找的就是符合條件的部分,* 星號表達式在這裏表示解包。

雖然這樣的解法很是騷氣,也建議思考背後實現的原理。


以上就是本篇的主要內容

歡迎關注微信公衆號《書所集錄》
相關文章
相關標籤/搜索