实现将 string 字符串转换为 integer 整数的 atoi 函数。

这个函数在必要时会将开头的空白字符抛弃直到第一个非空字符被发现。然后,从这个字符开始,取可选的正负号打头,后面跟尽可能多的数字,将他们解释为一个数值。

这个字符串可以在组成整数的后面包含额外的字符,这些额外的字符会被忽略并且不会对这个函数的行为造成任何影响。

如果开头的非空字符序列不是一个有效的数值,或者因为给定的字符串是空或者只包含空白字符而不存在这样一个序列的话,将不会执行任何转换。

如果没有任何有效转换可以被执行,将会返回一个零值。

注意:

  • 只有空格符 ' ' 会被认为是空白字符。
  • 假设我们是在仅能存储 32 位有符号整数范围 [ -231, 231 - 1] 内的数的环境下处理这个问题。如果最后数值超过了这个范围可以表示的数,那么 INT_MAX 或 INT_MIN 会被返回。

Example 1:

Input: "42"
Output: 42

Example 2:

Input: "   -42"
Output: -42
Explanation: The first non-whitespace character is '-', which is the minus sign.
             Then take as many numerical digits as possible, which gets 42.

Example 3:

Input: "4193 with words"
Output: 4193
Explanation: Conversion stops at digit '3' as the next character is not a numerical digit.

Example 4:

Input: "words and 987"
Output: 0
Explanation: The first non-whitespace character is 'w', which is not a numerical 
             digit or a +/- sign. Therefore no valid conversion could be performed.

Example 5:

Input: "-91283472332"
Output: -2147483648
Explanation: The number "-91283472332" is out of the range of a 32-bit signed integer.
             Thefore INT_MIN (−231) is returned.

解法:

题目意思很好理解,忽略字符串开头的空白字符后,如果后面有一段连续的字符序列可以转换为包括正号开头在内的数字的话,返回这个数字。否则返回 0 。

要注意的点有:

  • 开头可能有一堆空白字符,这些都要跳过。

  • 可以以正负号开头。意味着第一位可能是正号、负号或者数字。
  • 有效序列后面可以跟其他无效字符。
  • 最后要检查数字是否溢出。

代码实现:

/**
 * @param {string} str
 * @return {number}
 */
var myAtoi = function(str) {
    const INT = { max: 2 ** 31 - 1, min: - (2 ** 31) };
    let res = { start: 0, length: 0 };
    let lastType = 0; // 0-whitespace 1-sign 2-number 3-invalid
    const sign = {
        '-': true,
        '+': true,
    };
    const digit = {
        '1': true,
        '2': true,
        '3': true,
        '4': true,
        '5': true,
        '6': true,
        '7': true,
        '8': true,
        '9': true,
        '0': true,
    };
    
    for (let i = 0; i < str.length; i++) {
        let char = str.charAt(i);
        switch (lastType) {
            case 0:
                if (char == ' ') break; //ignore
                if (sign[char]) {
                    res.start = i;
                    lastType = 1;
                } else if (digit[char]) {
                    res.start = i;
                    res.length ++;
                    lastType = 2;
                } else {
                    lastType = 3;
                }
                break;
            case 1:
                if (digit[char]) {
                    res.length += 2;
                    lastType = 2;
                } else {
                    lastType = 3;
                }
                break;
            case 2:
                if (digit[char]) {
                    res.length ++;
                } else {
                    lastType = 3;
                }
                break;
            default:
                break;
        }
        if (lastType == 3) break;
    }
    
    let result = Number(str.substr(res.start, res.length));
    if (result > INT.max) result = INT.max;
    if (result < INT.min) result = INT.min;
    return result;
};