描述:请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:
- 读入字符串并丢弃无用的前导空格
- 检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
- 读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
- 将前面步骤读入的这些数字转换为整数(即,“123” -> 123, “0032” -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
- 如果整数数超过 32 位有符号整数范围 [−2^31, 2^31 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −2^31 的整数应该被固定为 −2^31 ,大于 2^31 − 1 的整数应该被固定为 2^31 − 1 。
- 返回整数作为最终结果。
代码:
class Solution {
public:
int myAtoi(string s) {
int len = s.size(), i = 0, num = 0, answer = 0;
bool isNegative = false;
while(s[i] == ' ') i++; //跳过空白字符
if(s[i] == '-') isNegative = true, i++; //确定数字正负号,不要忘记++避免错误
else if(s[i] == '+') i++;
while(i < len)
{
if(isdigit(s[i])) //判断s[i]是否为数字字符
{
num = s[i] - '0';//char转换为int
answer = answer*10 + num;
i ++;
}
else //遇到非数字的字符则直接退出循环
{
break;
}
}
if(isNegative) //改变符号
{
answer = -answer;
num = -num;
}
if (answer > INT_MAX / 10 || (answer == INT_MAX / 10 && num > 7)) return INT_MAX; //判断越界的情况
if (answer < INT_MIN / 10 || (answer == INT_MIN / 10 && num < -8)) return INT_MIN;
return answer;
}
};
顺便学习一下python的流氓做法:正则表达式
代码:
class Solution:
def myAtoi(self, s: str) -> int:
return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2**31 - 1), -2**31)
解释:
- 使用正则表达式【 ^:匹配字符串开头,[+-]:代表一个+字符或-字符,?:前面一个字符可有可无,\d:一个数字,+:前面一个字符的一个或多个,\D:一个非数字字符 】
- 【 max(min(数字, 2**31 - 1), -2**31) 】用来防止结果越界
**弹出和推入数字 & 溢出前进行检查** 一下内容来自LeetCode第7题的官方题解: 当 temp = rev⋅10 + pop 时会导致溢出。
幸运的是,事先检查这个语句是否会导致溢出很容易。
为了便于解释,我们假设 rev\text{rev}rev 是正数。
-
如果 temp=rev⋅10+pop 导致溢出,那么一定有 rev≥INTMAX/10。
-
如果 rev>INTMAX/10,那么temp=rev⋅10+pop一定会溢出。
-
如果 rev==INTMAX/10,那么只要 pop>7,temp=rev⋅10+pop 就会溢出。
当 rev为负时可以应用类似的逻辑。
class Solution {
public:
int reverse(int x) {
int rev = 0;
while (x != 0) {
int pop = x % 10;
x /= 10;
if (rev > INT_MAX/10 || (rev == INT_MAX / 10 && pop > 7)) return 0;
if (rev < INT_MIN/10 || (rev == INT_MIN / 10 && pop < -8)) return 0;
rev = rev * 10 + pop;
}
return rev;
}
};