题目:
给你一个 32 位的有符号整数 x ,返回将 x 中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1] ,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入:x = 123
输出:321
示例 2:
输入:x = -123
输出:-321
示例 3:
输入:x = 120
输出:21
示例 4:
输入:x = 0
输出:0
提示:
-231 <= x <= 231 - 1
笔者思路
这题比较简单,无非就是加减乘除而已,使用乘以10再加新数字ret = ret * 10 + rem的形式即可。
主要是要考虑对于一些特殊数组会溢出的问题。比如12****8979,这个数组反过来很可能就大于INT_MAX了。使用乘以10再加上新数字的算法,就可能异常。
可以反过来,思考,既然乘以10再加上新数字的结果跟INT_MAX比较可能异常,使用INT_MAX减去新数字再除以10跟原数字相比即可。
所以代码如下:
class Solution {
public:
int reverse(int x) {
if(x==INT_MIN)//剔除这个特殊情况后,x就对称了
return 0;
bool f = (x >= 0);//符号
int ret = 0;
x = f ? x : -x;
while(x > 0){
int rem = x % 10;//余数
x = x / 10;//新的x
if((INT_MAX - rem) / 10 < ret){//直接算可能溢出,反过来由INT_max计算出预计算出的ret是否满足
return 0;
}
ret = ret * 10 + rem;//如果没有上面的排查,这里会溢出
}
return f ? ret : -ret;
}
};
官方解答
class Solution {
public:
int reverse(int x) {
int rev = 0;
while (x != 0) {
if (rev < INT_MIN / 10 || rev > INT_MAX / 10) {
return 0;
}
int digit = x % 10;
x /= 10;
rev = rev * 10 + digit;
}
return rev;
}
};
官方又了一堆数学公式,证明了只需要考虑 (rev < INT_MIN / 10 || rev > INT_MAX / 10)即可。其实跟我的代码(INT_MAX - rem) / 10 < ret)是差不多的意思,只是我的代码这样免得更多的数学思考了。
另外有一点,我的算法之所以将负数区分开考虑,是因为我实在不知道-12除以10到底是余2还是余8还是-2。不过经过实验-12/10=-1......-2。所以官方的解答更为简便一些。