字串轉換整數JS
阿新 • • 發佈:2022-04-18
/** * @param {string} str * @return {number} */ var myAtoi = function(str) { // 自動機類 class Automaton{ constructor() { // 執行階段,預設處於開始執行階段 this.state = 'start'; // 正負符號,預設是正數 this.sign = 1; // 數值,預設是0 this.answer = 0; /* 關鍵點: 狀態和執行階段的對應表 含義如下: [執行階段, [空格, 正負, 數值, 其他]]View Code*/ this.map = new Map([ ['start', ['start', 'signed', 'in_number', 'end']], ['signed', ['end', 'end', 'in_number', 'end']], ['in_number', ['end', 'end', 'in_number', 'end']], ['end', ['end', 'end', 'end', 'end']] ]) } // 獲取狀態的索引 getIndex(char) {if (char === ' ') { // 空格判斷 return 0; } else if (char === '-' || char === '+') { // 正負判斷 return 1; } else if (typeof Number(char) === 'number' && !isNaN(char)) { // 數值判斷 return 2; } else { // 其他情況 return 3; } }/* 關鍵點: 字元轉換執行函式 */ get(char) { /* 易錯點: 每次傳入字元時,都要變更自動機的執行階段 */ this.state = this.map.get(this.state)[this.getIndex(char)]; if(this.state === 'in_number') { /* 小技巧: 在JS中,對字串型別進行減法操作,可以將得到一個數值型(Number)的值 易錯點: 本處需要利用括號來提高四則運算的優先順序 */ this.answer = this.answer * 10 + (char - 0); /* 易錯點: 在進行負數比較時,需要將INT_MIN變為正數 */ this.answer = this.sign === 1 ? Math.min(this.answer, Math.pow(2, 31) - 1) : Math.min(this.answer, -Math.pow(-2, 31)); } else if (this.state === 'signed') { /* 優化點: 對於一個整數來說,非正即負, 所以正負號的判斷,只需要一次。 故,可以降低其判斷的優先順序 */ this.sign = char === '+' ? 1 : -1; } } } // 生成自動機例項 let automaton = new Automaton(); // 遍歷每個字元 for(let char of str) { // 依次進行轉換 automaton.get(char); } // 返回值,整數 = 正負 * 數值 return automaton.sign * automaton.answer; };
自動機
我們的程式在每個時刻有一個狀態s,每次從序列中輸入一個字元c,並根據字元c 轉移到下一個狀態s'。
這樣,我們只需要建立一個覆蓋所有情況的從s與c對映到s'的表格即可解決題目中的問題。
來源:力扣(LeetCode)
字串str中的每個字元,都有可能是以下的四種類型中的一種:
- 空格字元' '(Space)
- 正負號+和-(Sign)
- 字串型的數值(Number)
- 除以上三種情況外的任何情況(Other)
階段分析
如果想要將字串轉換為整數,那麼必然會經歷這四個有序的階段:
- 開始轉換(start)
- 判斷正負(signed)
- 生成數值(in_number)
- 結束轉換(end)
梳理為表格形式
解決的問題:字串轉換整數 (atoi)
可以想到Javascript 的 parseInt(),使用這個API,進行嘗試。
parseInt(string, radix):
string:要被解析的值。如果引數不是一個字串,則將其轉換為字串。字串開頭的空白符將會被忽略。
radix(可選):需要轉換的進位制,介於 2 到 36。
返回值: 如果被解析引數的第一個字元無法被轉化成數值型別,則返回NaN。
- 無視開頭空格(√)
- 返回有符號整數(√)
- 無視整數部分後的字元(√)
- 範圍在
32
位內(含)(x) - 其他情況返回
0
(x)
需要注意:
在使用parseInt(string, radix)這一API時,如果不傳入radix引數,會有兩種特殊情況:
如果字串 string 以"0x"或者"0X"開頭, 則基數是16 (16進位制).
如果字串 string 以"0"開頭, 基數是8(八進位制)或者10(十進位制),那麼具體是哪個基數,取決與ECMAScript的版本。
/** * @param {string} s * @return {number} */ var myAtoi = function(s) { const number = parseInt(s, 10); if(isNaN(number)) { return 0; } else if (number < Math.pow(-2, 31) || number > Math.pow(2, 31) - 1) { return number < Math.pow(-2, 31) ? Math.pow(-2, 31) : Math.pow(2, 31) - 1; } else { return number; } };