Skip to content

一般是要判断是数字a是10倍的速度增长,判断

a > Integer.MAX_VALUE/10 || (a == Integer.MAX_VALUE/10 && a1 > 7)a < Integer.MIN_VALUE/10 || (a == Integer.MIN_VALUE/10 && a1 < -8)

以上条件成立,则说明a数字再增长10倍,就会溢出
其中(a1是最后1位)

INFO

有时,后半部份a == Integer.MAX_VALUE/10 && a1 > 7可能会被省略,具体要看题目的要求 作为对比,下面看两个题的代码

数字反转

package algorithm.数字和数学;

/**
 *
 * [7. 整数反转](https://leetcode.cn/problems/reverse-integer/description/)
 *
 */
public class reverse {

    // 第一种写法:标准写法
    public static int reverse(int x) {
        int res = 0;
        while (x != 0) {
            // 获得末尾数字
            int tmp = x % 10;
            // 判断是否大于最大32位整数,也可以使用Integer.MAX_VALUE/10来代替214748364
            if (res > 214748364 || (res == 214748364 && tmp > 7)) return 0;
            // 判断是否小于最下的32位整数
            if (res<-214748364 || (res == -214748364 && tmp < -8)) return 0;
            res = res * 10 + tmp;
            x /= 10;
        }
        return res;
    }


    // 最大正整数:2147483647  == /10 ==> 214748364
    // 最小负整数:-2147483648 == /10 ==> -214748364

    // 第二种写法:
    // ⚠️⚠️为什么上面的代码里(res == 214748364 && tmp > 7)和(res == -214748364 && tmp < -8)删掉也是对的

    // 因为,如果输入的数字位数小于【最大数字的位数】,那么一定是不会溢出的
    // 拿463847412举例翻转之后是214748364是9位数字,这个数正好是【最大正整数的10分之一】
    // 翻转前8位的时候,都比【最大正整数的10分之一】要小,因为【最大正整数的10分之一】是9位数字
    // 剩下最后1位数字的时候,x/=10就是0了,退出了循环
    // 也就是说,无论最后1位是多少,因为位数小于【最大数字的位数】,不等到res == Integer.MAX_VALUE/10这个判断就已经退出循环了

    // 如果输入数字位数大于等于【最大数字的位数】
    // 先看大于的情况,是不存在大于的情况的,因为输入数字就溢出了,显然是不可能的
    // 那么只有位数等于的情况
    // 当 前9位正好等于214748364时,最后1位不可能为7
    // 因为 214748364是反转得来的,10位的输入数字,要想不溢出,高位必须是1或者2,不可能为7
    // 同理,也不需要判断 -8
    public static int reverse2(int x) {
        int res = 0;
        while (x != 0) {
            int tmp = x % 10;
            if (res > Integer.MAX_VALUE/10 || res < Integer.MIN_VALUE/10) return 0;
            res = res * 10 + tmp;
            x /= 10;
        }
        return res;
    }



    public static void main(String[] args) {
    }

}

字符串转换整数

package algorithm.字符串;

/**
 *
 * [8. 字符串转换整数 (atoi)](https://leetcode.cn/problems/string-to-integer-atoi/description/)
 *
 *  这里不涉及算法,涉及日常编程的边界问题和数据处理
 *
 */
public class myAtoi {

    public int myAtoi(String s) {
        int len = s.length();
        char[] charArray = s.toCharArray();

        // 1. 去除前导空格
        int index = 0;
        while (index < len && charArray[index] == ' ') {
            index++;
        }

        // 2. 如果已经遍历完成(针对极端用例 "          ")
        if (index == len) return 0;

        // 3. 如果出现符号字符,仅第1个有效,并记录正负
        int sign = 1;
        char firstChar = charArray[index];
        if (firstChar == '+') {
            index++;
        } else if (firstChar == '-') {
            index++;
            sign = -1;
        }

        // 4. 将后续出现的数字字符进行转换
        // 不能使用long类型
        int res = 0;
        while (index < len) {
            char currChar = charArray[index];
            // 先判断不合法情况
            if (currChar > '9' || currChar < '0') {
                break;
            }

            // 解决溢出问题的经典处理方式
            if (res > Integer.MAX_VALUE / 10 || (res == Integer.MAX_VALUE / 10 && (currChar - '0') > Integer.MAX_VALUE % 10))  {
                return Integer.MAX_VALUE;
            }
            if (res < Integer.MIN_VALUE / 10 || (res == Integer.MIN_VALUE / 10 && (currChar - '0') > -(Integer.MIN_VALUE % 10))) {
                return Integer.MIN_VALUE;
            }

            // 合法情况下,才考虑转换,每一步都把符号位乘进去
            res = res * 10 + sign * (currChar - '0');
            index++;
        }
        return res;
    }
}