LeetCode (8): String to Integer (atoi)

 目】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!!!】

 1 if(str == null || str.equals("")) {
 2             return 0;
 3         }
 4         str = str.trim();
 5         char tmp;
 6         boolean signflag = false;//是否之前已经有正负号的标志位
 7         long result = 0L;//用long做累加器,可以防止溢出
 8         char sign = ' ';//记录正负号
 9         int count = 0;//位数计数器,用来做溢出可能的判断
10         if(str.charAt(0) == '+' || str.charAt(0) == '-') {
11             sign = str.charAt(0);
12             signflag = true;
13         } else if(!Character.isDigit(str.charAt(0))) {
14             return 0;
15         } else { //第一位是数字
16             result = str.charAt(0) - '0';
17         }
18         for(int i = 1; i < str.length(); i++){
19             tmp = str.charAt(i);
20 
21             //情况1, 遇到非数字的字符,因为之前第一位检查过是否为正负号, 所以,这里如果不是数字,就要看第一位是什么
22             if(!Character.isDigit(tmp)) {
23                 if(i==1) {
24                     //第一位后紧跟着非数字字符
25                     if(Character.isDigit(str.charAt(0))){//如果第一位是数字,那就break.
26                         break;
27                     }
28                     return 0;
29                 } else {
30                     //不是紧跟着出现,说明前面已经有数字
31                     break;
32                 }
33             } else {//遇到数字
34                 count++;
35                 result = result * 10 + (tmp - '0');
36                 if(count >= 9){//数字位数达到10位,需要考虑溢出问题
37                     if(signflag && sign == '-') { //有符号,且为负
38                         if(result * -1 < Integer.MIN_VALUE) return Integer.MIN_VALUE;
39                     }
40                     if(signflag && sign == '+') { //有符号,且为正
41                         if(result > Integer.MAX_VALUE) return Integer.MAX_VALUE;
42                     }
43                     //这个可能性不能漏了,没有符号,按照正的对待
44                     if(!signflag && result > Integer.MAX_VALUE) {return Integer.MAX_VALUE ;}
45                 }
46             }
47         }
48         //程序走到这里,说明没有溢出,我们也累加得到了数字result, 但是result是无符号的,所以需要考虑正负号
49         if(signflag && sign == '-') { //如果有符号且为负,转换符号输出
50             return (int)result * -1;
51         }
52         if(signflag && sign == '+') { //如果有符号且为正,直接输出
53             return (int)result;
54         }
55         return (int)result; //这种情况是捡漏的,如果无符号,走到这里,直接输出
MyAtoi

【反思 】

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

同时,要懂总结规律。例如本题中,由于一开始的' '全都可以跳过,所以可以直接trim(),去掉他们的干扰。trim后,第一个字符要么是正负号,要么是数字才可以接受。否则直接return 0。通过trim的操作,直接在后面的循环里可以不用再考虑' '的情况,遇到非数字只需要考虑当前情况即可。

 

 

 

 

 

原文地址:https://www.cnblogs.com/lupx/p/leetcode-8.html