关于LeetCode中String to Integer (atoi)一题的理解

来源:互联网 发布:第一次欧洲旅游知乎 编辑:程序博客网 时间:2024/06/07 06:57

题目如下:

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.

Update (2015-02-10):
The signature of the C++ function had been updated. If you still see your function signature accepts a const char * argument, please click the reload button  to reset your code definition.

Requirements for atoi:

The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.

    这次没脸贴自己的代码了,因为写的太烂了,虽然也强行Accepted了......这次直接贴评论区的代码,写得太好了。这次题目的主要难点就是要考虑输入的各种情况,考虑不周的话很容易出现各种错误,这次我的代码也是3次才Accepted。评论区中的一个票数最高的答案好像是用C++写的,我稍微改了一些,改成了java版本,但是思路还是大致一样的。代码如下,当然肯定进行了测试,已经Accepted了。

<span style="font-size:14px;">    public int myAtoi(String str) {               if (str.length() == 0){            return 0;        }        int sign = 1;        int base = 0;        int i = 0;        while (i < str.length() && str.charAt(i) == ' '){            i++;        }        if ( i < str.length() && (str.charAt(i) == '-' || str.charAt(i) == '+')){            if (str.charAt(i) == '-'){                sign = -1;            }else{                sign = 1;            }            i++;        }        while (i < str.length() && str.charAt(i) >= '0' && str.charAt(i) <= '9' ){            if (base > Integer.MAX_VALUE / 10 || (base == Integer.MAX_VALUE/10 && str.charAt(i)-'0' > 7)){                if (sign == 1){                    return Integer.MAX_VALUE;                }else{                    return Integer.MIN_VALUE;                }            }            base = 10 * base + (str.charAt(i) - '0');            i++;        }        return base * sign;    }</span>
    这种问题一般就是考察对各种可能的输入进行一个分类,最后写出的代码要能适应不同的输入情况。本题中的输入大致可以分为以下这几种情况:

(1)输入字符串长度为0;

(2)输入字符串中的开始部分包含若干空格或者输入的字符串中全部都是空格;

(3)符号,有三种情况,负号、正号及无符号;

(4)输入的字符串转化之后的数字可能已经溢出了int类型的最大值或最小值;

(5)无效输入,即字符串根本不能表示任何数字。

    这个程序的巧妙之处在于,程序本身的执行顺序其实也隐性地包含了一些判定。即第一步:判断字符串开始空格出现的情况,第二步判断符号的情况,第三部判断数字的情况。如果这三步都能够被正确执行,说明输入的是一个“合法”的字符串。举个例子:输入为“  +-1”,这里的输出结果就是0。因为一个数字中符号只能出现最多一次,这个出现最多一次的符号后面应该接数字。咱们看程序的运行情况,先判断字符串开始部分“空格”的情况,在遇到“+”的时候,开始判断“+”的情况。然后这条if语句就执行完毕了,直接开始执行下一个while循环,而在“+”后面的字符是“-”,“-”是不满足while循环开始的条件的,while循环不会被执行,base的值还是开始时设置的值0,所以最后返回的base*sign的值就是0。

    下一个点就是关于是否溢出的判断,需要注意的是这里的base的类型是int,所以想用base直接和MAX_INT、MIN_INT比较大小是不现实的,因为base本身就可能发生溢出。所以这里用到的方法就是不直接进行比较,由于每次while循环都会产生一个base,这个base的值是逐渐变大的,所以我们就要在一进入循环的时候就比较base的大小,这个比较base的大小是看base有没有“潜力”溢出。怎么看有没有“潜力”呢?分两种情况,(1)base的大小已经大于MAX_INT / 10,这说明下次进行乘10操作的时候肯定要溢出,所以我们可以直接根据符号返回int最大值或最小值了;(2)base的大小等于MAX_INT / 10,那就要看当前位字符是不是大于7,如果符号是正,那么大于7即大于2147483647,肯定溢出,如果符号为负,那么大于7即小于-2147483647,此时应该返回int的最小值-2147483648。至于按位从左到右计算10进制数的值这个就很简单了,不赘述了,之前的博客中也有讲。

    这种题做多了对各种输入的考虑就会细致一些了。



1 0