题目要求:
请你来实现一个 myAtoi(string s) 函数,使其能将字符串转换成一个 32 位有符号整数(类似 C/C++ 中的 atoi 函数)。函数 myAtoi(string s) 的算法如下:
1读入字符串并丢弃无用的前导空格
2检查下一个字符(假设还未到字符末尾)为正还是负号,读取该字符(如果有)。 确定最终结果是负数还是正数。 如果两者都不存在,则假定结果为正。
3读入下一个字符,直到到达下一个非数字字符或到达输入的结尾。字符串的其余部分将被忽略。
4将前面步骤读入的这些数字转换为整数(即,"123" -> 123, "0032" -> 32)。如果没有读入数字,则整数为 0 。必要时更改符号(从步骤 2 开始)。
5如果整数数超过 32 位有符号整数范围 [−231, 231 − 1] ,需要截断这个整数,使其保持在这个范围内。具体来说,小于 −2^31 的整数应该被固定为 −2^31 ,大于 2^31 − 1 的整数应该被固定为 2^31 − 1 。
6返回整数作为最终结果。
来源:力扣(LeetCode)第八题
思路1(有错误):
对每一个元素进行遍历,然后满足要求进行处理,不满足不处理或者退出遍历。具体来说,对String中的每一个元素,进行判断。先判断是否是空格,是空格直接下次遍历;判断是否为符号位,我想用一个变量标记的。再判断这个元素是不是数字,是数字就用num = num*10 + (as-48)更新取到的数字。最后如果有数据且读到非数字的元素,则直接退出。最后根据标记判断是否加“+”、“-”。
java代码:
class Solution {
public int myAtoi(String s) {
String flag = "";//标记正负符号
int num = 0;
for(int i = 0; i < s.length(); i++){
int as = s.charAt(i);
//第一位是空格,不处理
if(as == 32){
coutinue;
}
//如果第一位为符号
if(as == 43){
flag = "+";
}
if(as == 45){
flag = "-";
}
//如果是数字
if(as>47&& as<58){
num = num*10 + (as-48);
}
//读到数字后,遇到不是数字的,直接退出
if(num!=0&&(as<=47&& as>=58)){
break;
}
}
if(flag == "+"){
return +num;
}
if(flag == "-"){
return -num;
}
return num;
}
}
问题:
按照我原来的理解,我觉得就是把数据读出来,然后去除前面的空格和非数字符号,这个应该输出987,但是出错了,正确的值是0。其实不出错,我编写的也有问题,没有考虑越界问题 。现在是我题目就没读懂。
思路二:
现在第一步是先读懂题目要求,看了大佬们的讲解,只要空格和正负号判断完后,接下来的第一个不是数字就退出。
首先判断前导空格,直到不是空格;判断是否是正负号,是的话,用flag进行标记;处理数字,如果接下来第一位不是数字,直接退出,是数字就一直遍历,直到退出数字。注意越界问题,这里我是直接借鉴大佬的(作者:liweiwei1419 链接:https://leetcode.cn/problems/string-to-integer-atoi/solution/jin-liang-bu-shi-yong-ku-han-shu-nai-xin-diao-shi-/)。
代码:
class Solution {
public int myAtoi(String s) {
int num = 0;//保留最后的整数数据
int temp;
int flag = 1;//表示正负号
char[] ch = s.toCharArray();
int i = 0;//遍历的顺序号
//1.判断前导空格,遇到空格就往后推迟一个
while(i='0'&&ch[i]<='9'){
temp = ch[i] - '0';
// 题目中说:环境只能存储 32 位大小的有符号整数,因此,需要提前判:断乘以 10 以后是否越界
if (flag*num>0&&(num > Integer.MAX_VALUE / 10 || (num == Integer.MAX_VALUE / 10 && (ch[i] - '0') > Integer.MAX_VALUE % 10))) {
return Integer.MAX_VALUE;
}
if (flag*num<0&&(flag*num < Integer.MIN_VALUE / 10 || (flag*num == Integer.MIN_VALUE / 10 && (ch[i] - '0') > -(Integer.MIN_VALUE % 10)))) {
return Integer.MIN_VALUE;
}
num = num*10 + temp;
i++;
}
return flag>0? +num:-num;
}
}
错的太多了。。。。。。。。。。。
补充,越界判断:首先我们来一个正数的举例,假设10进制中规定最大的数为100,现在有个数为1234,。如果我们迭代得到了12,而且下一个也是数字(数字3),如果不判断,必有12*10+3的一次迭代,123肯定超过了界限。因此得到12后,且下一位是数字时,就要判断。根据乘10的操作,可以比较12和100/10,如果12大于最大值除以10,则肯定越界。这样就对应着代码中的:
num > Integer.MAX_VALUE / 10
如果迭代过程中数字小于最大值除以10,则不会越界。那么等于呢?还以上面为例,如果某次迭代得到10,而且下一个字符也是数字(x),如果不判断,就有10*10+x的迭代结果,如果x=0,值为100(不越界),如果x>0(越界)。因此在相等时还要判断x和最大值的最后一位0的关系:
num == Integer.MAX_VALUE / 10 && (ch[i] - '0') > Integer.MAX_VALUE % 10)
用上面的两个判断就可以完全解决正数的越界问题。负数也是同样的道理,只要注意符号就可以
总结:最开始理解错了意思,搞了1个多小时都是错的。然后先看了其他人的解释和代码,下午自己编写了一次,一直错,最开始完全不会越界处理(第一次接触)。3个小时的编码+学习,真的要哭。
暑期编程PK赛 得CSDN机械键盘等精美礼品!


