给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
先上代码:
版本1:
public class Problem_0007_ReverseInteger {
public static int reverse(int x) {
//按照负数算,负数取正数永远大一位。int类型的取值范围-2147483648~2147483647
int p = x;
x = x > 0 ? -x : x;
int res = 0;
while (x != 0) {
res = res * 10 + x % 10;
x /= 10;
}
return p < 0 ? res : Math.abs(res);
}
}
存在问题,没有做溢出判断,比如x的值为2147483647,数字反转后大于int类型的最大值肯定会溢出
版本2:
public class Problem_0007_ReverseInteger {
public static int reverse(int x) {
//按照负数算,负数取正数永远大一位。int类型的取值范围-2147483648~2147483647
int p = x;
boolean neg = ((x >>> 31) & 1) == 1;
x = neg ? x : -x;
int m = Integer.MIN_VALUE / 10;
int n = Integer.MIN_VALUE % 10;
int res = 0;
while (x != 0) {
if (res < m || (res == m && x % 10 < n)) {
return 0;
}
res = res * 10 + x % 10;
x /= 10;
}
return p < 0 ? res : Math.abs(res);
}
}
判断一个数是正数还是负数,位运算比简单的三元运算符效率更高。
以上有两个需要解释的位置:
boolean neg = ((x >>> 31) & 1) == 1;用来判断x是否为正数,关于位运算,参考博客:blog.csdn.net/jiangyi711/…
因为int是带符号类型,所以最高位为符号位,于是最大表示的正数是:01111111 11111111 11111111 11111111,也就是2的31次方减1。 再来看最小值,-2的31次方的原码表示为10000000 00000000 00000000 00000000,此时最高位的数字既代表符号,也代表数值。求它的补码,所得结果为10000000 00000000 00000000 00000000。同样也是最高位既代表符号又代表数值,也就是说-2的31次方的原码和补码是相同的。
反转整数后防止溢出
if (res < m || (res == m && x % 10 < n)) { return 0; }res < m : 当在反转的过程中res < -214748364,此时再反转肯定会溢出int接受范围。
res == m && x % 10 < n : 当在反转的过程中res == -214748364,但是x % 10 < 8 此时再反转肯定也会溢出int接受范围。