
✅ LeetCode 29. 两数相除 — 思路总览
🧩 题目要求
给定两个整数 dividend 和 divisor,实现 整数除法,不能使用乘法 *、除法 / 和取余 % 运算符。
要求返回的结果应为 向零截断的整数商,即:
- 正数向下取整(如 8.3 → 8)
- 负数向上取整(如 -8.3 → -8)
如果商超出 int 范围(即 < -2³¹ 或 > 2³¹ - 1),返回 Integer.MAX_VALUE。
📌 解题思路
1️⃣ 特殊情况处理
- 如果
dividend = Integer.MIN_VALUE且divisor = -1,结果将溢出,需返回Integer.MAX_VALUE。
2️⃣ 记录结果正负号
- 用异或运算
(dividend < 0) ^ (divisor < 0)判断结果是否为负数。 - 将除数和被除数都转成正数进行计算,最后再加上符号。
3️⃣ 使用 减法 + 位运算(左移) 模拟除法
- 使用 位移(
<<)运算模拟乘法,通过将divisor不断翻倍来逼近dividend。 - 在每一轮中:
- 找出最大
divisor × 2^k,使得该值不超过当前dividend - 将该倍数加入到最终结果中
- 将
dividend减去该倍数的值,继续下一轮
- 找出最大
4️⃣ 为什么使用 long?
- 避免
Math.abs(Integer.MIN_VALUE)溢出问题 - 整个过程用
long类型进行中间计算更安全,最后再强转为int
⏱️ 时间复杂度分析
- 每一轮减法都用 指数方式减少
dividend,因此时间复杂度为:
O(log N),N 为 dividend 的绝对值
✅ 关键点总结
| 点位 | 说明 |
|---|---|
🚫 不使用 * / % | 用减法和位移代替 |
| ⚠️ 特判溢出 | MIN_VALUE / -1 会溢出 |
| 📈 位运算加速 | 倍增 divisor 快速逼近 |
| 💡 先判断再左移 | (temp << 1) 防越界 |
| 🔒 使用 long 类型 | 防止中间计算溢出 |
java solution
class Solution {
public int divide(int dividend, int divisor) {
// 处理特殊溢出情况, 当被除数是-2^31且除数是-1时, 此时得到的结果会溢出
if(dividend == Integer.MIN_VALUE && divisor == -1) {
return Integer.MAX_VALUE;
}
// 记录结果正负
boolean negative = (dividend < 0) ^ (divisor < 0);
// 使用 long 转换避免溢出,并且将被除数和除数都转换成正数,
long ldividend = Math.abs((long) dividend);
long ldivisor = Math.abs((long) divisor);
int result = 0;
// 我们利用内层的while循环来快速找到不超过ldividend的最大的ldivisor * 2^k,
while(ldividend >= ldivisor) { //这里是大于等于, 因为如果被除数等于除数时,还能继续减
long temp = ldivisor;
int multiple = 1; //multiple是不超过ldividend的最大的ldivisor * 2^k中2^k的值
//之所以这里while循环判断条件里是(temp << 1)而不是ldividend > temp
//是因为如果是后者, 那么我们得到的最终的temp会超过ldividend
while(ldividend > (temp << 1)) {
temp <<= 1;
multiple <<= 1;
}
ldividend -= temp;
result += multiple;
}
return negative ? -result : result;
}
}














![【数据结构】[特殊字符] 并查集优化全解:从链式退化到近O(1)的性能飞跃 | 路径压缩与合并策略深度实战](https://i-blog.csdnimg.cn/direct/81f95b97a06c4f66be7895afedcb590d.jpeg#pic_center)



