Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
开始拿到题的时候很单纯,直接分母减分子就好,忘了边界的情况,忘了分母为0的情况,也忘了除法是可以有负数的,果断TLE。
后来用分子每次增加一倍,与分母进行比较。如果不够的话继续加,反之则往回倒的方法,解决了TLE的问题。
比如分子是3的话,建一个二维数组来存分子倍数值和对应的次数。
3 6 12 24。。。
1 2 4 8 。。。
在往前加的过程中建立起这个二维数组,当加多了之后再依次往后退,直到与分母相等或者比分母大一点点。
之后就在一直纠结在Integer最大的正数(2147483647)和最小的负数(-2147483648)之间。由于-2147483648在算符号时不能直接abs转化成正数,会出现溢出的问题。又因为如果分子本身就是一个比较大的数,在往前加的过程中就会越界。还有,如果分子本身是个很小的负数,在减的时候减多了又会变成正数。。。。
最后想到可以用long扩展位数,先把分子分母都转成long,用异或(^)运算取正负号,结果由于在判断溢出时没有考虑符号,死在了-2147483648, 1用例上。后来用一个新的变量接收带最终符号的值,最终AC。
先贴上溢出的返回判断
long r = flag ? -result : result;
if(r > Integer.MAX_VALUE || r < Integer.MIN_VALUE){
return Integer.MAX_VALUE;
}
return (flag) ? -((int)result) : (int)result;
最后贴A过的代码
public int divide(int dividend, int divisor) {
long up = (long)dividend;
long down = (long)divisor;
boolean flag = (up < 0) ^ (down < 0); //1-,0+
up = Math.abs(up);
down = Math.abs(down);
if(down == 0 || up == 0) return 0;
long result = 0;
long temp = up;
long[][] times = new long[2][33];
times[0][0] = 1;
times[1][0] = down;
int i = 0;
while(temp > 0){
temp -= times[1][i];
result += times[0][i];
times[1][i+1] = times[1][i] + times[1][i];
times[0][i+1] = times[0][i] + times[0][i];
i++;
}
i--;
temp += times[1][i];
result -= times[0][i];
while(temp > 0 && i >= 0){
if(temp - times[1][i] < 0){
i--;
}
else{
temp -= times[1][i];
result += times[0][i];
}
}
long r = flag ? -result : result;
if(r > Integer.MAX_VALUE || r < Integer.MIN_VALUE){
return Integer.MAX_VALUE;
}
return (flag) ? -((int)result) : (int)result;
}
988 / 988 test cases passed.
Status: Accepted
Runtime: 340 ms