题目描述
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
说明:
- 被除数和除数均为 32 位有符号整数。
- 除数不为 0。
- 假设我们的环境只能存储32位有符号整数,其数值范围是[−2 31 ^{31} 31, 2 31 ^{31} 31−1]。本题中,如果除法结果溢出,则返回 2 31 ^{31} 31 − 1。
题解
方法:
最简单直接的想法是除法转换为加/减法,用被除数循环去加/减除数,这样就可以得出结果。
像上面这种方法,时间复杂度为线性阶。我们可以用除数倍增的方式来改进,改进后时间复杂度为对数阶。
public static int divide(int dividend, int divisor) {
if(dividend == Integer.MIN_VALUE && divisor == -1){
return Integer.MAX_VALUE;
}
if(dividend == 0){
return 0;
}
if(divisor == 0){
throw new ArithmeticException(" divisor can not be zero ");
}
// 记录最后是正数还是负数,1为正数,-1为负数
int sign = 1;
// 将被除数和除数转换为long类型,防止溢出
long dividendLong = dividend;
long divisorLong = divisor;
if(dividendLong < 0){
dividendLong = 0 - dividendLong;
sign = 0 - sign;
}
if(divisorLong < 0){
divisorLong = 0 - divisorLong;
sign = 0 - sign;
}
int result = 0;
int multiple = 1;
long initDivisorLong = divisorLong;
while(dividendLong >= divisorLong){
dividendLong = dividendLong - divisorLong;
result += multiple;
divisorLong += divisorLong;
multiple += multiple;
if(dividendLong < divisorLong){
divisorLong = initDivisorLong;
multiple = 1;
continue;
}
}
if(sign < 0){
result = 0 - result;
}
return result;
}
复杂度分析:
- 时间复杂度:O( log( dividend / divisor ) )。
- 空间复杂度:O(1)。