小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
题目描述
给定两个整数,被除数
dividend和除数divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。返回被除数
dividend除以除数divisor得到的商。整数除法的结果应当截去(
truncate)其小数部分,例如:truncate(8.345) = 8以及truncate(-2.7335) = -2
- 被除数和除数均为 32 位有符号整数
- 除数不为 0
- 假设我们的环境只能存储 32 位有符号整数,其数值范围是
[−2^31, 2^31 − 1]。本题中,如果除法结果溢出,则返回2^31 − 1
示例1 :
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333..) = truncate(3) = 3
示例2 :
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333..) = -2
解法:快速幂 + 二分
分析:为了避免超时,在每次减去除数的时候,尽可能减去除数的倍数,由于这里不能使用乘法,可以使用移位运算代替,每次向左移一位表示乘以2。这样每次减去 2^n ,可以加速找到解。
class Solution {
public int divide(int low, int up) {
boolean is_neg = false;
if(low < 0 && up > 0 || low > 0 && up < 0) is_neg = true;
long a = Math.abs((long)low), b = Math.abs((long)up);
// 将分子对应的比特位存下来, 不需要存31位,只需将小于分母的所有比特位保存下来就行
List<Long> exp = new ArrayList();
for(long i = b; i <= a; i = i << 1){
exp.add(i);
}
long k = 0;
//逆序遍历分子比特位, 如果被减数-减数那么说明商的这一位是1, 对应比特位由1<<i位得到
for(int i = exp.size() - 1; i >= 0; i--){
if(a >= exp.get(i)) {
a -= exp.get(i);
k += (long)1 << i;
}
}
if(is_neg) k *= -1;
if(k > Integer.MAX_VALUE || k < Integer.MIN_VALUE) return Integer.MAX_VALUE;
return (int)k;
}
}