问题链接
题目解析
给定一个32位有符号整数,求其反转数字。
解题思路
如果是简单反转的话,那这道题就太简单了。题目要求判断溢出问题,32位int类型的范围是-2147483648~2147483647。数字反转过后是有可能超出范围的,此时应该返回0。
最简单的想法是,反转结果用long long表示,其范围远超int,这样在反转过程中不会出现溢出问题,最后加以判断范围即可。
参考代码
class Solution {
public:
int reverse(int x) {
bool flag = true;
if (x < 0) {
flag = false;
x = -x;
}
long long res = 0;
while (x > 0) {
res = res * 10 + x % 10;
x /= 10;
}
if (res > INT_MAX) return 0;
if(flag) return res;
else return -res;
}
};
官方解法
官方的解答精简无比,有两点改进:
第一,没有处理正负号,为此特意去查了求余的特性,可参考负数求余运算,了解到C++在异号求余时尽可能让商大,所以在这里不影响计算,不过个人建议还是要区分正负号,因为在不同的情况下可能会因为这个小问题出错。
第二,没有用long long表示反转结果。想想也是,如果这一道题让你反转一个long long,你还有更大的类型吗?代码中直接用int表示反转结果,判断溢出条件也很是精妙。对此OJ还提出了问题:To check for overflow/underflow, we could check if ret > 214748364 or ret < –214748364 before multiplying by 10. On the other hand, we do not need to check if ret == 214748364, why? (214748364 即为 INT_MAX / 10)
想到输入的数范围在-2147483648~2147483647,计算INT_MAX / 10 = 214748364,如果res大于这个数,接下来的*10一定会超过范围;等于这个数,最后一位只可能是1或2,验证之后发现只能是1,2的话原数就超范围了,反转数也不会超过范围;小于这个数,*10之后不可能会超范围。
class Solution {
public:
int reverse(int x) {
int res = 0;
while (x != 0) {
if (abs(res) > INT_MAX / 10) return 0;
res = res * 10 + x % 10;
x /= 10;
}
return res;
}
};
其他解法
针对于官方解法,我们可以改进我们最初的写法。比如:依然用long long保存反转数,不区分正负号,核心代码如下(不过依然建议不使用):
long long res = 0;
while (x != 0) {
res = 10 * res + x % 10;
x /= 10;
}
return (res > INT_MAX || res < INT_MIN) ? 0 : res;
当然,对于判断溢出,可以通过除以10,判断结果是否已刚才一致,更好理解一些。代码如下:
class Solution {
public:
int reverse(int x) {
int res = 0;
while (x != 0) {
int t = res * 10 + x % 10;
if (t / 10 != res) return 0;
res = t;
x /= 10;
}
return res;
}
};
LeetCode All in One题解汇总(持续更新中...)
本文版权归作者AlvinZH和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.