思路
官方题解中有快速乘,那当然也就有快速除。思路就是模拟手动计算除法,二进制的除法和十进制也非常类似
解题过程
(1)首先要把除数和被除数“对齐” (2)然后除数和被除数进行比较,如果小于被除数则这一位商0,否则商1 (3)把每一位的01组装起来就是最终的结果 里面的一些边界问题还需要注意处理一下。
复杂度
时间复杂度: O(logN),其中N为被除数和除数倍数差,也即商。logN即为被除数和除数二进制的位数差,比如1011111/11,那么logN为7−2=5
空间复杂度: O(1)
class Solution {
public int divide(int dividend, int divisor) {
//如果除数是最小的int
if(divisor == Integer.MIN_VALUE){
return dividend == divisor?1:0;
}
//注意最小的int为-2^31,最大的int为2^31-1,如果商为2^31,越界,应返回2^31-1
if(dividend == Integer.MIN_VALUE){
if(divisor == 1){
return dividend;
}
if(divisor == -1){
return Integer.MAX_VALUE;
}
}
//为了便于统一进行移位等操作,都转成正数来处理
//如果dividend == Integer.MIN_VALUE,为了避免边界问题,先加上一个除数的绝对值,保证不越界
//如果加上了绝对值,后面商的绝对值需要+1,所以设置一个标志位
boolean plusOne = false;
if(dividend == Integer.MIN_VALUE){
dividend = dividend + (divisor>0?divisor:-divisor);
plusOne = true;
}
//都转为正数处理
boolean changeSymbol = false;
if(divisor < 0){
divisor = -divisor;
changeSymbol = !changeSymbol;
}
if(dividend < 0){
dividend = -dividend;
changeSymbol = !changeSymbol;
}
//不断把除数进行左移,直到和被除数对齐
int move = 0;
int constant = (1<<30);
while(divisor < dividend){
//如果符号位后紧接的一位,也就数字位的最高位已经为1了,则不应该再左移了
if( (divisor & constant) > 0){
break;
}
divisor <<= 1;
move++;
}
// int move = Integer.numberOfLeadingZeros(divisor) - Integer.numberOfLeadingZeros(dividend);
// divisor <<= move;
//模拟手算除法的过程,无非是二进制而已。十进制每一位可以商0-9,二进制中只能商0或1
int ans = 0;
for(int i = move;i>=0;i--){
if(dividend < divisor){
divisor >>= 1;
}else{
ans += (1 << i);
dividend -= divisor;
divisor >>= 1;
}
}
ans = plusOne?ans+1:ans;
return changeSymbol?-ans:ans;
}
}