Divide Two Integers 414
Question
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return 2147483647
Example
Given dividend = 100 and divisor = 9, return 11.
Solution
这道题要求不用乘,除和模操作完成除法操作。
基本思想是不断地减掉除数,直到为0为止。但是这样会太慢。
我们可以使用2分法来加速这个过程。不断对除数 * 2,直到它恰好比被除数小(即再乘2就会比被除数大)为止。加倍的同时,也记录下cnt,将被除数减掉加倍后的值,并且结果+cnt。因为是2倍地加大,所以速度会很快,指数级的速度。
但是因为不能用乘除操作,因此只能用位运算的方法,即左移1位 = * 2。
首先讨论一些边界情况:
如果除数为0,则被除数为正时,结果为正无穷,否则为负无穷
如果被除数为0,则返回0
如果被除数为正无穷除数为1或者被除数为负无穷除数为-1,则返回正无穷
如果被除数为正无穷除数为-1或者被除数为负无穷除数为1,则返回负无穷
记录一下结果的符号(即除数和被除数同号为+,异号为负),然后对除数和被除数取绝对值。注意:因为int最大2147483647,最小-2147483648,最小值直接abs后会溢出,所以要先讲被除数与除数转换为long之后再取绝对值,以防出现溢出的情况。
每次将b左移一定的位数,比如i位,使得b恰好小于a(即b< a),此时相当于b 2^i,然后再对剩下的数(即a-b 2^i)做刚才的操作,直到剩下的数小于b为止。看b总共乘以了多少power of 2,将其加和即可。
代码如下:
public class Solution {
/**
* @param dividend the dividend
* @param divisor the divisor
* @return the result
*/
public int divide(int dividend, int divisor) {
// Write your code here
if(divisor == 0){
return dividend >= 0 ? Integer.MAX_VALUE : Integer.MIN_VALUE;
}
if(dividend == 0){
return 0;
}
if((dividend == Integer.MAX_VALUE && divisor == 1) || (dividend == Integer.MIN_VALUE && divisor == -1)){
return Integer.MAX_VALUE;
}
if((dividend == Integer.MIN_VALUE && divisor == 1) || (dividend == Integer.MAX_VALUE && divisor == -1)){
return Integer.MIN_VALUE;
}
boolean signal = ((dividend > 0 && divisor > 0) || (dividend < 0 && divisor < 0))? true : false;
//在这里必须先取long再abs,否则int的最小值abs后也是原值(因为int最大2147483647,最小-2147483648,最小值abs后会溢出)
long a = Math.abs((long)dividend);
long b = Math.abs((long)divisor);
int result = 0;
while(a >= b){
int shift = 0;
while(a >= (b << shift)){
shift++;
}
shift--;
a -= b << shift;
result += 1 << shift;
}
return signal? result : -result;
}
}