首頁>技術>

實現一個 myAtoi(string s) 函式,使其能將字串轉換成一個 32 位有符號整數(類似 C/C++ 中的 atoi 函式)。

演算法如下:

第一步:

讀入字串並丟棄無用的前導空格

第二步:

檢查下一個字元(假設還未到字元末尾)為正還是負號,讀取該字元(如果有)。 確定最終結果是負數還是正數。 如果兩者都不存在,則假定結果為正。

第三步:

讀入下一個字元,直到到達下一個非數字字元或到達輸入的結尾。字串的其餘部分將被忽略。

第四步:

將前面步驟讀入的這些數字轉換為整數(即,"123" -> 123, "0032" -> 32)。如果沒有讀入數字,則整數為 0 。必要時更改符號(從步驟 2 開始)。

考慮邊界條件:

如果整數數超過 32 位有符號整數範圍 [−2^31, 2^31 − 1] ,需要截斷這個整數,使其保持在這個範圍內。具體來說,小於 −2^31 的整數應該被固定為 −2^31 ,大於 2^31 − 1 的整數應該被固定為 2^31 − 1 。

返回值:

返回有符號整數作為最終結果。

注意:

本題中的空白字元只包括空格字元 ' ' 。

除前導空格或數字後的其餘字串外,請勿忽略 任何其他字元。

舉個例子:

輸入:s = " -42"

輸出:-42

解釋:

第 1 步:" -42"(讀入前導空格,但忽視掉)

第 2 步:" -42"(讀入 '-' 字元,所以結果應該是負數)

第 3 步:" -42"(讀入 "42")

解析得到整數 -42 。

由於 "-42" 在範圍 [-231, 231 - 1] 內,最終結果為 -42 。

演算法核心步驟:

ans = ans * 10;//核心步驟1ans = ans + (s[j] - '0'); //核心步驟2

本次從字串取出的字元s[j],轉換為對應的數字(s[j] - '0'),與上一次取出的結果乘以10 相加,迴圈下去,就可以取出每一位字元,並轉換為一個有符號整數。

(s[j] - '0')這一步實現了,將一個列印字元轉換為對應的數字。

ASCII碼錶

下面就說說為什麼字元減’0’可以到相應的整數。現在比如我們要字元‘1’轉換成數字1,就這麼一個變化,我們注意到字元型常量用’ '括起來的原因是,它們在計算機中都以各自的ASCII表示。而‘1’的對應編碼是49的二進位制碼,但是我們的數字1,就等於1呀,所以為了由原來的‘1’實際上就是49的二進位制變成現在的1對應的二進位制1,只好用49-48=1了。但是在ASCII碼裡‘0’對應的剛好是48的二進位制碼,所以我們轉換的時候只需要‘1’-‘0’=1;就可以了。而數字的ASCII碼是按順序規定的。所以其它字元要轉換成數字都可以用減‘0’來表示。比如‘2’的ASCII是50,而我們要得到數字2,於是用‘2’-48=2了。看來當我們知道資料在計算機中的儲存規則的時候,問題就迎刃而解了。

根據已有演算法寫出實現程式碼:

第一步:讀入字串並丟棄無用的前導空格

while (' ' == s[i])//判斷有幾個前導空格    {        i++;    }

第二步:檢查下一個字元(假設還未到字元末尾)為正還是負號,讀取該字元(如果有)。 確定最終結果是負數還是正數。 如果兩者都不存在,則假定結果為正。

if ('+' == s[i] || '-' == s[i])    {//判斷是否存在符號,+或者-        if ('-' == s[i])        {//如果存在-符號,flag取為-1            flag = -1;        }        //i只加一次,符號只判斷一次,連著兩個符號非法        i++;    }

第三步:讀入下一個字元,直到到達下一個非數字字元或到達輸入的結尾。字串的其餘部分將被忽略。

for (int j = i; j < strlen(s); j++)    {       //空格、符號後邊必須是數字,如不是直接返回       if (s[j] < '0' || s[j] > '9')break;

第四步:將前面步驟讀入的這些數字轉換為整數(即,"123" -> 123, "0032" -> 32)。如果沒有讀入數字,則整數為 0 。必要時更改符號(從步驟 2 開始)。

ans = ans * 10;//核心步驟1ans = ans + (s[j] - '0'); //核心步驟2

考慮邊界條件:如果整數數超過 32 位有符號整數範圍 [−2^31, 2^31 − 1] ,需要截斷這個整數,使其保持在這個範圍內。具體來說,小於 −2^31 的整數應該被固定為 −2^31 ,大於 2^31 − 1 的整數應該被固定為 2^31 − 1 。

//為了防止溢位,要提前判斷是否有小於32位整數最小值的可能        if (ans  < IntMin / 10 || (ans  == IntMin / 10 && -(s[j] - '0') < IntMin % 10))         return IntMin; {//為了防止溢位,要提前判斷是否有大於32位整數最大值的可能        if (ans  > IntMax / 10 || (ans  == IntMax / 10 && (s[j] - '0') > IntMax % 10))        return IntMax;

由於邊界情況非常複雜,根據符號分為正數和負數處理部分:

 if(flag == -1)//處理負數部分       {        //為了防止溢位,要提前判斷是否有小於32位整數最小值的可能        if (ans  < IntMin / 10 || (ans  == IntMin / 10 && -(s[j] - '0') < IntMin % 10))         return IntMin;        ans = -ans * 10;//核心步驟1        ans = -ans + flag * (s[j] - '0');//核心步驟2       }  else//處理正數部分       {//為了防止溢位,要提前判斷是否有大於32位整數最大值的可能        if (ans  > IntMax / 10 || (ans  == IntMax / 10 && (s[j] - '0') > IntMax % 10))        return IntMax;        ans = ans * 10;//核心步驟1        ans = ans + (s[j] - '0'); //核心步驟2       } 

該題有點像腦經急轉彎題。

完整C語言程式碼:

#include<stdio.h>#include<stdlib.h>#include<string.h>#define INTMAX  ((unsigned)(-1)>>1)#define INTMIN  (~INTMAX)int myAtoi(char * s){    int IntMax = INTMAX;    int IntMin = INTMIN;    int ans = 0;    int i = 0;    int flag = 1;    while (' ' == s[i])//判斷有幾個前導空格    {        i++;    }    if ('+' == s[i] || '-' == s[i])    {//判斷是否存在符號,+或者-        if ('-' == s[i])        {//如果存在-符號,flag取為-1            flag = -1;        }        //i只加一次,符號只判斷一次,連著兩個符號非法        i++;    }    for (int j = i; j < strlen(s); j++)    {       //空格、符號後邊必須是數字,如不是直接返回       if (s[j] < '0' || s[j] > '9')break;       //數字分為整數和負數來判斷,方便確定邊界值       if(flag == -1)       {        //為了防止溢位,要提前判斷是否有小於32位整數最小值的可能        if (ans  < IntMin / 10 || (ans  == IntMin / 10 && -(s[j] - '0') < IntMin % 10))         return IntMin;        ans = -ans * 10;//核心步驟1        ans = -ans + flag * (s[j] - '0');//核心步驟2       }       else       {//為了防止溢位,要提前判斷是否有大於32位整數最大值的可能        if (ans  > IntMax / 10 || (ans  == IntMax / 10 && (s[j] - '0') > IntMax % 10))        return IntMax;        ans = ans * 10;//核心步驟1        ans = ans + (s[j] - '0'); //核心步驟2       }           }    return ans;}int main(){    char s[] = "-91283472332";    int ans = myAtoi(s);    printf("%d\n", ans);    return 0;}

LeetCode系列:

二叉樹系列:

4
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • 架構設計:系統間通訊——MQ:訊息協議(上)