题目描述
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。
函数 myAtoi(string s) 的算法如下:
读入字符串并丢弃无用的前导空格
检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −231 的整数应该被固定为 −231 ,大于 231 − 1 的整数应该被固定为 231 − 1 。
返回整数作为最终结果。
注意:
本题中的空白字符只包括空格字符 ' ' 。
除前导空格或数字后的其余字符串外,请勿忽略 任何其他字符。
示例 1:
输入:s = "42"
输出:42
解释:加粗的字符串为已经读入的字符,插入符号是当前读取的字符。
第 1 步:"42"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"42"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"42"(读入 "42")
^
解析得到整数 42 。
由于 "42" 在范围 [-231, 231 - 1] 内,最终结果为 42 。
示例 2:
输入:s = " -42"
输出:-42
解释:
第 1 步:" -42"(读入前导空格,但忽视掉)
^
第 2 步:" -42"(读入 '-' 字符,所以结果应该是负数)
^
第 3 步:" -42"(读入 "42")
^
解析得到整数 -42 。
由于 "-42" 在范围 [-231, 231 - 1] 内,最终结果为 -42 。
示例 3:
输入:s = "4193 with words"
输出:4193
解释:
第 1 步:"4193 with words"(当前没有读入字符,因为没有前导空格)
^
第 2 步:"4193 with words"(当前没有读入字符,因为这里不存在 '-' 或者 '+')
^
第 3 步:"4193 with words"(读入 "4193";由于下一个字符不是一个数字,所以读入停止)
^
解析得到整数 4193 。
由于 "4193" 在范围 [-231, 231 - 1] 内,最终结果为 4193 。
题解
这道题,太恶心了,我花了很久时间才通过,倒不是因为难,就是很多小的地方需要扣。
这道题简单来说就分四种情况:
1.不合法情况(也就是最开始就不合法):
首位字符不是数字、正负号、空格,这样的情况直接返回0就行
2.首位是0
首位是0的时候,又分两种情况:
1)0后面跟的数字
这种情况是合法情况,直接进行遍历字符串,入栈之后出栈计算最终结果即可;
2)0后面跟的字符
这种情况直接返回0,因为不合法;
3.首位是正负号
首位是正负号的又分两种情况:
1)空格完后是数字
跟上面的操作一样,入栈,出栈计算;
2)正负号(只能是正负号,其余的不行)
就从正负号后面开始遍历,入栈,出栈计算;
4.首位是空格
首位是正负号的情况同样包含了两种
1)后面跟是的0
2)正常数字
这两种情况,直接入栈,出栈计算就行,因为0不影响后面的最终结果;
除了以上所述的情况,其余情况都是非法情况;
那么直接上代码:
class Solution {
public:
int myAtoi(string s) {
/*考虑使用栈来实现
合法情况:1.首位为数字;2.首位为正负号;3.首位为空格 就这三种合法情况
首位是数字中又分首位为0和首位不为0
首位是空格中包含了空格完后是数字和正负号(只能是正负号,其余的不行)
首位是正负号的情况就包含了后面跟是的0和正常数字,其余均为0
*/
//排除调不合法情况
int res = 0,top=-1;//结果和栈顶指针
if((s[0]-'0'>=17 && s[0]-'0'<=42) || (s[0]-'0'>=49 && s[0]-'0'<=74) ||
(s[0]-'0'==-2))
{
res = 0;
std::cout<<res<<endl;
return res;
}
//合法情况
int stack[500000]={0};
//如果第一位是数字
if(s[0]-'0'>=0 && s[0]-'0'<=9)
{
int flag = 0;
if(s[0]=='0')//首位是0
{
for(int i=1;i<s.size();i++)
{
if(!(s[i]-'0'>=0 && s[i]-'0'<=9))//如果0后面跟的不是数字
{
res = 0;
cout<<res<<endl;
return res;
}
else if(s[i]-'0'>=1 && s[i]-'0'<=9){
s = s.substr(i, (s.size()-i));//截取当前位置到末尾
cout<<s<<endl;
break;
}
}
for(int i=0;i<s.size();i++)
{
if(s[i]-'0'>=0 && s[i]-'0'<=9)//如果当前是数字,则入栈
{
stack[++top] = s[i] - '0';
}
else
{
break;
}
}
//计算结果,出栈
for(;top>-1;top--)
{
if(res+stack[top]*pow(10,flag)<=2147483647)//判断是否溢出
{
res += stack[top]*pow(10,flag);
++flag;
}
else
{
res = 2147483647;
break;
}
}
}
else if(s[0]-'0'>=1 && s[0]-'0'<=9)//首位是非零数字
{
//直接循环入栈
stack[++top]=s[0]-'0';
for(int i=1;i<s.size();i++)
{
if(!(s[i]-'0'>=0 && s[i]-'0'<=9))//如果当前不是数字
{
break;
}
else
{
stack[++top]=s[i]-'0';
}
}
for(;top>-1;top--)
{
if(res+stack[top]*pow(10,flag)<=2147483647)//判断是否溢出
{
res += stack[top]*pow(10,flag);
++flag;
}
else
{
res = 2147483647;
break;
}
}
}
}
/*首位是空格的情况*/
else if(s[0]==' ')
{
int flag = 0;
for(int i=1;i<s.size();i++)
{
if(s[i]!=' ')//如果当前位置不是空格
{
if(!(s[i]-'0'>=0 && s[i]-'0'<=9) && s[i]!='+' && s[i]!='-')//不是数字,不是正负号,直接非法
{
res = 0;
return res;
}
//合法
else{
if(s[i]=='+' || s[i]=='-')//如果空格后面是正负号
{
if(s[i]=='-')
{
s=s.substr(i,s.size()-i);//把负号算进去
cout<<s<<endl;
break;
}
else
{
s=s.substr(i+1,s.size()-i);//从符号位的下一位截取到末尾
cout<<s<<endl;
break;
}
}
else if(s[i]-'0'>=0 && s[i]-'0'<=9)//如果空格后面是数字
{
s=s.substr(i,s.size()-i);//从当前截取
cout<<s<<endl;
break;
}
}
}
}
for(int i=(s[0]=='-'?1:0);i<s.size();i++)
{
if(s[i]-'0'>=0 && s[i]-'0'<=9)
{
stack[++top]=s[i]-'0';//入栈
}
else
{
break;
}
}
for(;top>-1;top--)
{
// res+=stack[top]*pow(10,flag);
// ++flag;
if(s[0]=='-')
{
if(res+(-(stack[top]*pow(10,flag)))>=-2147483648)//负数的情况
{
res+=-(stack[top]*pow(10,flag));
++flag;
}
else
{
res = -2147483648;
}
}
else
{
if(res+stack[top]*pow(10,flag)<=2147483647)
{
res+=stack[top]*pow(10,flag);
++flag;
}else res=2147483647;
}
}
}
else if(s[0]=='+' || s[0]=='-')//首位是正负号的情况
{
int flag=0;
if(!(s[1]-'0'>=0 && s[1]-'0'<=9))//符号后面不是数字,直接非法
{
res = 0;
return res;
}
else
{
for(int i=1;i<s.size();i++)
{
if(s[i]-'0'>=0 && s[i]-'0'<=9)
{
stack[++top]=s[i]-'0';//入栈
}
else
{
break;
}
}
for(;top>-1;top--)
{
// res+=stack[top]*pow(10,flag);
// ++flag;
if(s[0]=='-')
{
if(res+(-(stack[top]*pow(10,flag)))>=-2147483648)//负数的情况
{
res+=-(stack[top]*pow(10,flag));
++flag;
}
else
{
res = -2147483648;
}
}
else
{
if(res+stack[top]*pow(10,flag)<=2147483647)
{
res+=stack[top]*pow(10,flag);
++flag;
}else res=2147483647;
}
}
}
}
std::cout<<res<<endl;
return res;
}
};
最后跑出来的情况其实不太好(相比较大家的提交情况而言),这道题烦就烦在需要考虑很小的地方,比如int型越界的时候,需要判断是否越界,如果越界应该怎么做,还有就是符号的考虑,太细太细了!!
写到最后我才意识到,我的这个代码,有部分可以改改,比如数字的入栈,首位是0的情况,其实可以直接入队,反正0不影响最终结果。