[模拟|数位] leetcode 7 整数反转
1.题目
题目链接
给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。
示例 1:
输入: 123
输出: 321
示例 2:
输入: -123
输出: -321
示例 3:
输入: 120
输出: 21
注意:
假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。
2.分析
2.1.除法运算
可以屏蔽整数的低位,保留高位。
例如123 / 100 = 1,屏蔽了个位、十位,保留了百位。
2.2.取余运算
可以屏蔽整数的高位,保留低位。
例如123 % 10 = 3,屏蔽了十位、百位,保留了个位。
2.3.按位遍历
可以通过反复"余10"、"除10"的过程来从低到高遍历整数的每一位。例如:
int x = 123;
while(x) {
cout << x % 10;
x /= 10;
}
输出为321。如果将结果存储在一个新数中,就相当于完成了"整数反转"的过程。
2.4.溢出判断
本题特殊点在于给出的整数在反转后是可能溢出的。那么首先我们得先知道32位有符号整数的上下限。在C++中,可以利用
cout << INT_MAX << endl;// 2147483647
cout << INT_MIN << endl;//-2147483648
来获取整数的最大值与最小值。这两个常量定义在limits.h中。
那么如何判断当前数反转后是否已经溢出呢?
情况1:
如果当前数反转后前9位的绝对值已经大于INT_MAX(INT_MIN)的前9位(214748364),并且该数还有剩余位没有被遍历,那么该数在反转完毕后一定会溢出:
//rev为当前反转后的结果
if (rev > INT_MAX / 10 || rev < INT_MIN / 10) {
return 0;
}
情况2:
如果当前数反转后前9位的绝对值恰好等于INT_MAX(INT_MIN)的前9位(214748364),并且该数还有剩余位没有被遍历,那么还需要判断接下来的一位是否会造成溢出:
//rev为当前反转后的结果
if ((rev == INT_MAX / 10 && pop > 7) || (rev == INT_MIN / 10 && pop < -8)) {
return 0;
}
3.代码
class Solution {
public:
int reverse(int x) {
int rev = 0;//反转结果
while (x != 0) {
int pop = x % 10;//取出当前最低位
x /= 10;//移除当前最低位
//最大值溢出
if (rev > INT_MAX / 10 || (rev == INT_MAX / 10 && pop > 7)) {
return 0;
}
//最小值溢出
if (rev < INT_MIN / 10 || (rev == INT_MIN / 10 && pop < -8)) {
return 0;
}
//rev左移一位并加入新的一位
rev = rev * 10 + pop;
}
return rev;
}
};