LeetCode 8 字符串转数字 细节之处总结
总结,本题需要注意的细节之处有以下几点:
1 字符如何转换为数字?
可以直接使用字符char-‘0’得到对应的数字,然后乘10累加
int tmp=(s[i]-'0');
Ans=Ans*10+tmp;
2 如何在不使用long数据的情况下,判断数据是否溢出?
由于int可表示的范围是[-231 ,231-1]
也就是[-2147483648 ,2147483647]
我们可以通过比较当前值Ans与231/10的大小关系来判断是否溢出
- Ans<231/10 ;此时显然可以继续进行加乘 ,因为Ans*10最大等于2147483630,加上新的一个十进制数,显然小于2147483647
- Ans>231/10 ;此时显然不可以继续进行加乘 ,因为Ans*10最小等于2147483650,已经大于2147483647
- Ans==231/10 ;此时就需要根据正负数进行判断了:如果为正,那么,tmp>7时,就溢出了,此时Ans最小为2147483648;如果为负,那么,tmp>8时,就溢出了,此时Ans最小为2147483649;
在实现的时候,由于我是将符号用flag来存储,所以如果按照上述的规则编写,代码如下:
while ((s[i] >= '0' && s[i] <= '9') && i < s.length())
{
//为数字就继续
if (Ans > MAXINT / 10)
return flag == 1 ? MAXINT : MININT;
if (Ans == MAXINT / 10 && flag == 1 && s[i] > '7')
return MAXINT;
if (Ans == MAXINT / 10 && flag == -1 && s[i] > '8')
return MININT;
int tmp = (s[i] - '0');
Ans = Ans * 10 + tmp;
i++;
}
会报溢出错误?
原来是,我将flag单独拎出来,那么在判断负数的时候,如果tmp =8;那么Ans =2147483648;然后最后返回flag*Ans,结果为-2147483648;但是Ans =2147483648已经越界了,所以这里可以将两个判断合成一个,根据flag的正负号来判断最终输出的是MAXINT 还是MININT
while ((s[i] >= '0' && s[i] <= '9') && i < s.length())
{
//为数字就继续
if (Ans > MAXINT / 10)
return flag == 1 ? MAXINT : MININT;
if (Ans == MAXINT / 10 && s[i] > '7')
return flag==1?MAXINT:MININT;
int tmp = (s[i] - '0');
Ans = Ans * 10 + tmp;
i++;
}
return Ans * flag;
}
END
class Solution {
private:
const int MAXINT=2147483647;
const int MININT=-2147483648;
public:
int myAtoi(string s) {
//确定符号正负;去掉前导零;超过32位限制就输出最大最小数
//先找到起始的负号,或者第一个数字,然后将字符串转换为数字,在这个过程中判断是否溢出
int Ans=0;
int flag=1;
int i=0;
//去除前导空格
while(s[i]==' '&&i<s.length()){
i++;
}
//确定是否直接是数字
if(s[i]=='-') {
flag=-1;
i++;
}
else if(s[i]=='+'){
flag=1;
i++;
}
else if(s[i]<'0'&&s[i]>'9'){
return 0;
}
while((s[i]>='0')&&(s[i]<='9')&&i<s.length()){
//为数字就继续
int tmp=s[i]-'0';
if(Ans>(MAXINT/10)||Ans==MAXINT/10&&tmp>7) return flag==1?MAXINT:MININT;
Ans=Ans*10+tmp;
i++;
}
return Ans*flag;
}
};
刷题总结类 文章被收录于专栏
这里记录一些刷题时候的总结思考