一、问题
给你一个 32 位的有符号整数 x
,返回将 x
中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−231, 231 − 1]
,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
二、解题思路
这道题的核心在于反转整数,并且需要处理溢出问题。我们需要考虑如何在反转过程中避免超出 32 位整数范围。具体解题思路如下:
-
处理正负数:
- 给定的整数
x
可能是正数或负数。 - 处理时,我们可以先记录下符号,然后对其绝对值进行反转操作,最后再根据符号恢复结果。
- 给定的整数
-
逐位提取与重构:
- 可以使用 逐位提取法 来反转数字。通过不断提取
x
的最后一位数字,逐步构建反转后的数字。 - 提取最后一位数字的方式是使用
x % 10
,然后将其添加到结果reversedNum
中。 - 将
x
整除 10 去掉最后一位数字,继续这个过程直到x
为 0。
- 可以使用 逐位提取法 来反转数字。通过不断提取
-
防止溢出:
- 由于反转后的数字可能会超过 32 位整数的范围(即
[-2^31, 2^31 - 1]
),所以在每次操作之前,我们需要检查结果reversedNum
可能的溢出情况。 - 检查溢出条件:在每次更新
reversedNum
之前,判断reversedNum
是否会在添加下一位数字时超过范围。如果会超过范围,直接返回 0。
- 由于反转后的数字可能会超过 32 位整数的范围(即
三、代码
public class Solution {
public int reverse(int x) {
int reversedNum = 0; // 用来保存反转后的数字
while (x != 0) {
// 取 x 的最后一位数字
int lastDigit = x % 10;
// 检查是否会溢出(针对 32 位有符号整数的范围 [-2^31, 2^31-1])
if (reversedNum > Integer.MAX_VALUE / 10 ||
(reversedNum == Integer.MAX_VALUE / 10 && lastDigit > 7)) {
return 0; // 溢出,返回 0
}
if (reversedNum < Integer.MIN_VALUE / 10 ||
(reversedNum == Integer.MIN_VALUE / 10 && lastDigit < -8)) {
return 0; // 溢出,返回 0
}
// 更新反转后的数字
reversedNum = reversedNum * 10 + lastDigit;
// 去掉 x 的最后一位
x /= 10;
}
return reversedNum;
}
}
四、复杂度分析
- 时间复杂度:O(log(x)),因为整数
x
可能有最多log(x)
位数字,我们每次处理一位。 - 空间复杂度:O(1),我们只使用了常量空间存储中间变量。