请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数。

函数 myAtoi(string s) 的算法如下:

空格:读入字符串并丢弃无用的前导空格(” “)

符号:检查下一个字符(假设还未到字符末尾)为 ‘-‘ 还是 ‘+’。如果两者都不存在,则假定结果为正。

转换:通过跳过前置零来读取该整数,直到遇到非数字字符或到达字符串的结尾。如果没有读取数字,则结果为0。

舍入:如果整数数超过 32 位有符号整数范围 [−2^31, 2^31 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −2^31 的整数应该被舍入为 −2^31 ,大于 2^31 − 1 的整数应该被舍入为 2^31 − 1 。

返回整数作为最终结果。

示例 1:

输入:s = “42”

输出:42

解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。

带下划线线的字符是所读的内容,插入符号是当前读入位置。
第 1 步:”42”(当前没有读入字符,因为没有前导空格)

第 2 步:”42”(当前没有读入字符,因为这里不存在 ‘-‘ 或者 ‘+’)

第 3 步:”42”(读入 “42”)

示例 2:

输入:s = “ -042”

输出:-42

解释:

第 1 步:” -042”(读入前导空格,但忽视掉)

第 2 步:” -042”(读入 ‘-‘ 字符,所以结果应该是负数)

第 3 步:” -042”(读入 “042”,在结果中忽略前导零)

示例 3:

输入:s = “1337c0d3”

输出:1337

解释:

第 1 步:”1337c0d3”(当前没有读入字符,因为没有前导空格)

第 2 步:”1337c0d3”(当前没有读入字符,因为这里不存在 ‘-‘ 或者 ‘+’)

第 3 步:”1337c0d3”(读入 “1337”;由于下一个字符不是一个数字,所以读入停止)

示例 4:

输入:s = “0-1”

输出:0

解释:

第 1 步:”0-1” (当前没有读入字符,因为没有前导空格)

第 2 步:”0-1” (当前没有读入字符,因为这里不存在 ‘-‘ 或者 ‘+’)

第 3 步:”0-1” (读入 “0”;由于下一个字符不是一个数字,所以读入停止)

示例 5:

输入:s = “words and 987”

输出:0

解释:

读取在第一个非数字字符“w”处停止。

提示:

  • 0 <= s.length <= 200
  • s 由英文字母(大写和小写)、数字(0-9)、’ ‘、’+’、’-‘ 和 ‘.’ 组成

解题思路

这条题目需要注意的应该就是’ ‘, ‘+’, ‘-‘这三个特殊的字符

  • 如果是字符串前面遇到的空格,都可以无视,继续判断下一个字符,当然觉得麻烦的话,也可以使用 trim 的方式将前后的空字符串都去掉,这样只要遇到空字符,那么就停止遍历
  • 如果是在遇到数字之前遇到的’+’或者’-‘,那么可以设置一个标志位用于标识这个数字的正反

遍历字符串,遇到数字之后,可以使用拼接字符串最后转Number的方式,也可以通过数学方式拼接即res = res * 10 + x,res是上一轮的数字,x是这一轮的数字。这种方式的实现效率比字符串要高一些。继续遍历直到字符串结束或者遇到别的字符终止。

代码

var myAtoi = function(s) {
//创建一个hashset 用于存放0-9的数字,当然也可以通过判断字符的ASCII码在48-57之间判断是'0'-'9'
const numberSet = new Set(['0', '1', '2', '3', '4', '5', '6', '7', '8', '9'])

let flag = 0 // 0代表还没读运算符和数字 1代表读了运算符 2代表读了数字了
let positiveOperator = true //用于控制是正数还是负数
let result = 0

for (let i = 0; i < s.length; i++) {
const charValue = s.charAt(i)

if (flag === 0 && charValue === ' ') { //如果还没有读到操作符和数字,且当前字符为空字符那么进入下一轮
continue
}

if (flag === 0 && (charValue === '+' || charValue === '-')) { //如果还没有读到操作符和数字的话,且当前字符为操作符的话
positiveOperator = charValue === '+' //判断操作符
flag = 1 //标志为设置为已经读取操作符
continue
}

if (numberSet.has(charValue)) { //既不是操作符也不是空字符的话,判断是否是数字
result = result * 10 + Number(charValue) //将当前数字推入结果的最后一位
flag = 2 //标志为设置为已经读取数字
continue
}
break //为其他字符的话,循环终止
}

if (!positiveOperator) { //如果运算符是-,那么将结果取反
result = -result
}

//如果结果超出[-2^31, 2^31 - 1]范围,那么将其缩回范围中
if (result > 2147483647) {
return 2147483647
}
if (result < -2147483648) {
return -2147483648
}

return result
};