8

思路

这道题和上一道题有点类似, 基本实现很容易, 主要难度在于corner case的考虑...

实现

我的实现过程中考虑了如下几种情况的corner case :

  1. 输出为空字符串 --> 返回0.
  2. 输出中带有小数或者其他非法字母(eg : 3.12) --> 在出现的非法字母的地方停止.
  3. 输出越界, 超过最大或者最小整数 --> 正数返回最大整数, 负数返回最小整数.

提交

不幸的是仍然错了3次, 主要漏掉了这两种corner case :

  1. 字符串前面带一串空格.
  2. 字符串前面带正号(一般都会想到字符串前面要么带负号要么不带, 这里带正号的情况很难想到)

同时我还考虑错了一种情况 : 就是在如何判断数据越界的问题上, 我采用了上一题中使用的那种回算的方式, 但是我发现那个想法其实是有问题的, 比如 x 经过 x * 10 + y 的结果是z, 那么如果z越界 (z - y) / 10 == x有可能为真, 也有可能为假, 这个不是绝对的. 例如可以考虑x = 214748364 * 10, y = 9的情况, 这时候 x * 10 + y的值显然溢出了, 但是前面那个等式确实是成立的. 那么到底什么情况下为真什么情况下为假呢?

  1. 如果是后面的加法导致的越界, 那么为真, 因为加法就算越界也保持可逆性.
  2. 如果是前面的乘法就已经越界, 那么为假.

所以第7题之所以可以那么判断, 是因为它输入的也是一个int, 要想出现加法越界, 除非最后一位是大于7, 也就是输入int的第一位就大于7, 这样的话输入的int已经越界了, 所以不可能出现加法越界的情况, 所以要特别小心.

代码

public class Solution {
    public int myAtoi(String str) {
        str = str.trim();
        boolean isNegative = false;
        boolean isOverflow = false;
        long re = 0;

        for(int i = 0; i < str.length(); ++i){
            if(i == 0 && (str.charAt(i) == '-' || str.charAt(i) == '+')){
                isNegative = str.charAt(i) == '-';
                continue;
            }

            if(Character.isDigit(str.charAt(i))){
                re = re * 10 + str.charAt(i) - '0';
                if(re < 0x80000000l) continue;
                else    isOverflow = true;
            }
            break;
        }

        if(isNegative){
            return isOverflow ? 0x80000000 : -(int)re;
        }
        else{
            return isOverflow ? 0x7fffffff : (int)re;
        }
    }
}

最佳实现

对于我的解法的改进, 网上主要集中在不使用long, 而是判断Integer.MAX_VALUE/10 < total || Integer.MAX_VALUE/10 == total && Integer.MAX_VALUE %10 < digit(total 是当前的re, digit 是当前i指向的字符), 通过在计算之前判断是否会溢出即可. 比较简单, 所以这里就不贴具体代码了.

原文地址:https://www.cnblogs.com/nzhl/p/6227708.html