一道真正考察「边界意识」的基础算法题
一、题目背景
给你一个 32 位有符号整数 x,
请你将它的 数字部分反转。
⚠️ 如果反转后的结果 超出 int 范围
[-2³¹, 2³¹ - 1],则返回 0。
示例说明
输入:123
输出:321
输入:-123
输出:-321
输入:120
输出:21
输入:1534236469
输出:0(反转后溢出)
二、这道题真正想考什么?
很多人第一反应是:
“不就是反转一下吗?”
但这道题的核心 不在反转,而在:
- ✅ 是否理解 int 的取值边界
- ✅ 是否意识到 乘法会溢出
- ✅ 是否知道 溢出必须提前判断
📌 这是面试官非常喜欢的“基础筛选题”
三、核心思路:数学拆位
不使用字符串,纯整数操作。
三个固定步骤
digit = x % 10; // 取末位
x /= 10; // 去末位
res = res * 10 + digit;
直观示例(x = 123)
| 当前 x | 取末位 | res |
|---|---|---|
| 123 | 3 | 3 |
| 12 | 2 | 32 |
| 1 | 1 | 321 |
四、真正的难点:整数溢出怎么处理?
Java 中 int 的范围
Integer.MAX_VALUE = 2147483647
Integer.MIN_VALUE = -2147483648
危险操作在这里:
res = res * 10 + digit;
⚠️ 一旦 res * 10 超出范围,Java 不会报错,而是直接变成错误值!
👉 所以必须 在乘 10 之前判断
五、溢出判断的核心逻辑
正数溢出判断
if (res > Integer.MAX_VALUE / 10 ||
(res == Integer.MAX_VALUE / 10 && digit > 7)) {
return 0;
}
为什么是 7?
Integer.MAX_VALUE = 2147483647
如果 res == 214748364:
- digit ≤ 7 → 安全
- digit ≥ 8 → 溢出
负数溢出判断
if (res < Integer.MIN_VALUE / 10 ||
(res == Integer.MIN_VALUE / 10 && digit < -8)) {
return 0;
}
为什么是 -8?
Integer.MIN_VALUE = -2147483648
负数比正数 多一个可用值
六、完整 Java 解法
class Solution {
public int reverse(int x) {
int res = 0;
while (x != 0) {
int digit = x % 10;
x /= 10;
// 正数溢出
if (res > Integer.MAX_VALUE / 10 ||
(res == Integer.MAX_VALUE / 10 && digit > 7)) {
return 0;
}
// 负数溢出
if (res < Integer.MIN_VALUE / 10 ||
(res == Integer.MIN_VALUE / 10 && digit < -8)) {
return 0;
}
res = res * 10 + digit;
}
return res;
}
}
七、为什么不推荐 String 解法?
虽然你可以这样写:
new StringBuilder(String.valueOf(x)).reverse();
但问题是:
- ❌ 回避了溢出问题
- ❌ 不符合题目考察意图
- ❌ 面试官不买账
📌 这道题是“整数题”,不是字符串题
八、复杂度分析
| 项目 | 复杂度 |
|---|---|
| 时间复杂度 | O(log₁₀ n) |
| 空间复杂度 | O(1) |
九、常见易错点总结
- ❌ 先乘 10 再判断溢出(已经晚了)
- ❌ 忘记负数也要判断
- ❌ 用 long 偷懒绕过问题
- ❌ 不理解为什么是 7 和 -8
十、核心一句话总结
整数反转不难,
难的是在“整数边界”内安全地反转。
这道题是很多经典题的基础:
- 回文数
- 字符串转整数(Atoi)
- 整数运算溢出判断