• 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的操作,直接在后面的循环里可以不用再考虑' '的情况,遇到非数字只需要考虑当前情况即可。

     

     

     

     

     

  • 相关阅读:
    SQL server 数据库迁移到mysql
    MVC+EF之仓库模式
    MVC+EF之多表关联数据更新
    省市联动下拉菜单的实现
    MVC+EF之Attribute
    网页制作
    MVC5+EF6之排序、过滤、分页
    MVC5+EF6之分部视图(Partial View)
    Bookstap初步了解
    java8新特性学习三(Stream API)
  • 原文地址:https://www.cnblogs.com/lupx/p/leetcode-8.html
Copyright © 2020-2023  润新知