一、题目描述
给你一个 32 位的有符号整数 x
,返回将 x
中的数字部分反转后的结果。
如果反转后整数超过 32 位的有符号整数的范围 [−2^31, 2^31 − 1]
,就返回 0。
假设环境不允许存储 64 位整数(有符号或无符号)。
示例 1:
输入:x = 123 输出:321
示例 2:
输入:x = -123 输出:-321
示例 3:
输入:x = 120 输出:21
示例 4:
输入:x = 0 输出:0
提示:
-2^31 <= x <= 2^31 - 1
二、解题思路
-
确定反转限制: 由于题目要求反转后的整数不能超过32位有符号整数的范围(-2^31到2^31-1),我们需要在反转过程中不断检查当前的反转值是否超出这个范围。
-
处理符号位: 由于我们不能直接处理64位整数,我们需要在反转过程中单独处理符号位。这意味着我们需要在反转完成后,根据原始整数的符号位来确定最终结果的符号。
-
反转整数: 使用循环和位操作来逐位反转整数。在每次迭代中,我们从原始整数中提取最低位,将其添加到反转后的整数中,并更新原始整数。
-
检查范围: 在每次迭代中,我们需要检查反转后的整数是否已经超出了32位整数的范围。这可以通过比较反转后的整数与32位整数的最大值(Integer.MAX_VALUE)和最小值(Integer.MIN_VALUE)来实现。
-
返回结果: 如果在整个反转过程中没有超出范围,那么在循环结束后,我们可以根据原始整数的符号位来确定最终的反转结果。如果超出了范围,我们需要返回0。
-
编写代码: 根据上述思路,编写代码实现反转逻辑。在代码中,我们需要使用循环来处理每一位数字,同时在每一步中检查反转后的值是否合法。
这个解题思路的核心在于理解整数反转的过程,并在每一步中确保结果不会超出32位整数的范围。通过这种方式,我们可以在不使用64位整数的情况下,安全地反转32位有符号整数。
三、具体代码
class Solution {
public int reverse(int x) {
// 初始化反转后的数字
int reversed = 0;
// 初始化符号位
int sign = (x < 0) ? -1 : 1;
// 将x转换为正数,以便反转
x = Math.abs(x);
// 反转数字
while (x > 0) {
// 取出当前位
int digit = x % 10;
// 检查是否超出32位整数范围
if (reversed > Integer.MAX_VALUE / 10 || (reversed == Integer.MAX_VALUE / 10 && digit > 0)) {
return 0;
}
// 检查是否超出32位整数范围(负数情况)
if ((reversed * 10 + digit) < 0) {
return 0;
}
// 将当前位添加到反转后的数字
reversed = reversed * 10 + digit;
// 移除已处理的位
x /= 10;
}
// 如果原始数字是负数,反转后的数字也需要是负数
return reversed * sign;
}
}
四、时间复杂度和空间复杂度
1. 时间复杂度
- 时间复杂度:O(n)。
- 时间复杂度主要取决于循环的次数。
- 在最坏的情况下,我们需要处理一个32位的整数,这意味着循环将执行32次(因为每次循环处理一个数字位)。
- 因此,时间复杂度是 O(n),其中 n 是整数的位数。在这个特定的例子中,n 最大为 32。
2. 空间复杂度
- 空间复杂度:O(1)。
- 空间复杂度主要考虑的是程序运行过程中所需的额外存储空间。
- 在这个代码中,我们使用了两个变量
reversed
和sign
来存储反转后的数字和符号位。 - 这些变量在整个函数执行过程中都保持不变,因此空间复杂度是 O(1),即常数空间复杂度。
这里的 n 是整数的位数,对于32位整数,n 的最大值为32。在实际应用中,这个算法对于任何长度不超过32位的整数都是有效的,因此时间复杂度和空间复杂度都是固定的。
五、总结知识点
- 位操作:`x % 10`:取整数的最低位(即个位);`x /= 10`:将整数除以10并向下取整,移除最低位。
- 数学运算:`Math.abs(x)`:获取整数的绝对值,用于处理负数。
- 条件判断:`if` 语句用于检查反转过程中是否超出了32位整数的范围;`&&` 和 `||` 逻辑运算符用于组合多个条件。
- 循环控制:`while` 循环用于逐位反转整数。
- 数据类型和范围检查:了解 `int` 类型在Java中的范围(-2^31 到 2^31-1);在反转过程中,需要检查反转后的数字是否超出了 `int` 类型的范围。
- 符号处理:使用 `sign` 变量来记录原始整数的符号,以便在反转完成后正确处理负数。
- 边界条件处理:在反转过程中,需要处理边界条件,例如当反转后的数字接近 `Integer.MAX_VALUE` 或 `Integer.MIN_VALUE` 时,需要特别小心,以避免溢出。
- 代码风格和可读性:代码中的注释有助于理解逻辑流程;使用变量名如 `reversed` 和 `sign` 来提高代码的可读性。
- 错误处理:当反转后的数字超出范围时,代码返回0,这是一种错误处理机制。
- 算法效率:代码尽可能地避免了不必要的计算,例如在检查是否超出范围时,只检查了必要的条件。
以上就是解决这个问题的详细步骤,希望能够为各位提供启发和帮助。