您的位置:首页 > 其它

LeetCode (8): String to Integer (atoi)

2015-09-14 14:28 375 查看
目】LeetCode(8: String to Integer (atoi)

URL: https://leetcode.com/problems/string-to-integer-atoi/
【描述】

Implement atoi to convert a string to an integer.

Hint: Carefully consider all possible input cases. If you want a challenge, please do not see below and ask yourself what are the possible input cases.

Notes: It is intended for this problem to be specified vaguely (ie, no given input specs). You are responsible to gather all the input requirements up front.

【中文描述】

给一个字符串,要求转成integer。就这么一句话,不过有hint:

需要考虑各种可能的情况。

————————————————————————————————————————————————————————————

【初始思路】

题目也很直接的说,就是故意说这个模糊的,就是要考验你对于各种情况考虑的周不周全。但是个人感觉这个题设计还是有点问题。既然你不想让大家看下面的提示内容,那你就还是应该是多少说清楚,比如最明显的几种情况,字符串为空怎么处理,为null怎么处理,overflow了怎么处理。

所有这些东西,只能点开下面的详细提醒,才能看到。然后,先根据自己的理解,整理了一部分:

(1) if the string is "   " or "" or null,  should return 0
(2) str = "3124123fah1;kjf;lasdf", should return 3124123
(3) str = "      fafa123fnaf21j", should return 0
(4) str = "     -312341", should return -312341
(5) str = "ajklfla;hf;f", should return 0

然后根据这几个例子开撸。

首先,我们直接把str.trim()一下,然后情况就简单了。如果第一个字符是正负号或者数字,就接着从第二个字符开始判断。如果第一个字符直接就是特殊字符,直接return 0.

其次,遍历是肯定的,for(int i =0;i<str.length();i++),然后charAt(i)取出每个字符

第三,遇到'+'或者'-'怎么处理。由于之前已经判断过第一个字符是不是正负号,所以从第二个字符开始无需再判断正负号,全部按照非法字符对待;

第四,遇到非数字字符怎么处理。这个相对简单一点,如果当前是第二位,那么由于第一位有可能是数字,所以需要考虑第一位的情况。

  if(第一位是数字) break;

else { //说明第一位不是数字,那只能是正负号

return 0;

}

如果当前不是第二位,那就简单,直接break就好了。

第五,剩下的可能性,就只有数字了。定义一个累积器,把遇到的数字加起来就行了。

这就够了么?

溢出溢出溢出!!!重要的事情说三遍!

如果溢出怎么办?还好题目要求很人性化,只要溢出就返回Integer.MAX_VALUE 或者 Integer.MIN_VALUE。那溢出的判断就简单了!

累积的过程中,给一个记位器count,每加一位数字,count++。每次在遇到数字需要累加之前,先count++,然后判断是否>=9(读者请考虑为何是9),如果<9,肯定不会溢出,累加然后continue即可。

如果 count >= 9, 就有可能溢出。我们让累加器先累加出结果,然后把结果和MAXVALUE,MINVALUE做比较,如果溢出,直接返回对应的MAXVALUE或者MINVALUE即可。

同时,由于有可能有正负号,所以在累加结果出来后,需要根据正负号情况,分情况判断。

最后,如果溢出判断通过了,循环结束了,剩下的就是输出累加结果。同样的,根据正负号判断一下,如果没有正负号,按照正数对待,输出即可。

【Show me the Code!!!】

if(str == null || str.equals("")) {
return 0;
}
str = str.trim();
char tmp;
boolean signflag = false;//是否之前已经有正负号的标志位
long result = 0L;//用long做累加器,可以防止溢出
char sign = ' ';//记录正负号
int count = 0;//位数计数器,用来做溢出可能的判断
if(str.charAt(0) == '+' || str.charAt(0) == '-') {
sign = str.charAt(0);
signflag = true;
} else if(!Character.isDigit(str.charAt(0))) {
return 0;
} else { //第一位是数字
result = str.charAt(0) - '0';
}
for(int i = 1; i < str.length(); i++){
tmp = str.charAt(i);

//情况1, 遇到非数字的字符,因为之前第一位检查过是否为正负号, 所以,这里如果不是数字,就要看第一位是什么
if(!Character.isDigit(tmp)) {
if(i==1) {
//第一位后紧跟着非数字字符
if(Character.isDigit(str.charAt(0))){//如果第一位是数字,那就break.
break;
}
return 0;
} else {
//不是紧跟着出现,说明前面已经有数字
break;
}
} else {//遇到数字
count++;
result = result * 10 + (tmp - '0');
if(count >= 9){//数字位数达到10位,需要考虑溢出问题
if(signflag && sign == '-') { //有符号,且为负
if(result * -1 < Integer.MIN_VALUE) return Integer.MIN_VALUE;
}
if(signflag && sign == '+') { //有符号,且为正
if(result > Integer.MAX_VALUE) return Integer.MAX_VALUE;
}
//这个可能性不能漏了,没有符号,按照正的对待
if(!signflag && result > Integer.MAX_VALUE) {return Integer.MAX_VALUE ;}
}
}
}
//程序走到这里,说明没有溢出,我们也累加得到了数字result, 但是result是无符号的,所以需要考虑正负号
if(signflag && sign == '-') { //如果有符号且为负,转换符号输出
return (int)result * -1;
}
if(signflag && sign == '+') { //如果有符号且为正,直接输出
return (int)result;
}
return (int)result; //这种情况是捡漏的,如果无符号,走到这里,直接输出


MyAtoi

【反思 】

遇到这种需要考虑N多种情况的题,不要一个情况一个情况分别对待。要懂得归并,很多问题,其实合并后是一个问题。

同时,要懂总结规律。例如本题中,由于一开始的' '全都可以跳过,所以可以直接trim(),去掉他们的干扰。trim后,第一个字符要么是正负号,要么是数字才可以接受。否则直接return 0。通过trim的操作,直接在后面的循环里可以不用再考虑' '的情况,遇到非数字只需要考虑当前情况即可。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: