题目 : Divide two integers without using multiplication, division and mod operator. If it is overflow, return MAX_INT.
我们不实用除法进行整数除法运算,如果溢出的话,我们就返回整形的最大值。
1、我们第一想到的是直接相减(a, b),被除数不断的减去除数看最多能减几次,就返回。
然而很容易TLE.
public class Solution {
public int divide(int dividend, int divisor) {
long count = 0;
if(divisor == 0){
return Integer.MAX_VALUE;
}
int ret = 1;
if((dividend < 0 && divisor > 0)||(dividend > 0 && divisor < 0)){
ret = -1;
}
long divid = dividend;
divid = Math.abs(divid);
long divis = divisor;
divis = Math.abs(divis);
while(divid >= divis) {
divid = divid - divis;
count ++;
}
if(ret * count > Integer.MAX_VALUE || ret * count < Integer.MIN_VALUE){
return Integer.MAX_VALUE;
}
return (int)(ret * count);
}
}
2、于是我们想能不能通过为运算进行操作呢例如(15,4),向右移一位的话,意味着缩小二倍,我们就不断的缩小,直到被除数刚好小于除数。
即最多只能右移一位 ,此刻 15 - 2 * 4 = 7 ,然后对 7又进行上述的操作,7不能右移 所以 最后 7 - 4 = 3 此刻 总共减去4的次数是 3 ,代码如下
public class Solution {
public int divide(int dividend, int divisor) {
if(divisor == 0){
return Integer.MAX_VALUE;
}
int ret = -1;
if(((dividend>>31)^(divisor >> 31)) == 0){
ret = 1;
}
long divid = dividend;
long divis = divisor;
long result = helpDivide(Math.abs(divid),Math.abs(divis));
if(result > Integer.MAX_VALUE && ret == 1){
return Integer.MAX_VALUE;
}
return ret * (int)result;
}
public long helpDivide(long dividend, long divisor){
if(dividend < divisor){
return 0;
}else{
long sub = 0;
int i = 1;
int count = 0;
for(;i < 32 ;i++){
if((dividend >> i) < divisor){
break;
}
count ++;
}
sub = dividend - (long)(Math.pow(2,count)*divisor);
return (long)Math.pow(2,count)+helpDivide(sub,divisor);
}
}
}
我们对他进行优化,此刻超过了89% 36ms Java:
public class Solution {
public int divide(int dividend, int divisor) {
if(divisor == 0){
return Integer.MAX_VALUE;
}
int ret = 1;
if((dividend ^ divisor) < 0){
ret = -1;
}
long divid = dividend;
long divis = divisor;
long result = helpDivide(Math.abs(divid),Math.abs(divis));
if(result > Integer.MAX_VALUE && ret == 1){
return Integer.MAX_VALUE;
}
return ret * (int)result;
}
public long helpDivide(long dividend, long divisor){
if(dividend < divisor){
return 0;
}else{
long sub = 0;
int i = 1;
int count = 0;
for(;i < 32 ;i++){
if((dividend >> i) < divisor){
break;
}
count ++;
}
sub = dividend - (long)(Math.pow(2,count)*divisor);
return (long)Math.pow(2,count)+helpDivide(sub,divisor);
}
}
}
4,此外还有一种其他的思考方式我们看除数不断的调整,直到调整到刚好是不大于被除数,看增加了多少倍,此刻 82.64%
public class Solution {
public int divide(int dividend, int divisor) {
if (divisor == 0 || (dividend == Integer.MIN_VALUE && divisor == -1))
return Integer.MAX_VALUE;;
int sign = ((dividend ^ divisor) < 0) ? -1 : 1;
long dvd = Math.abs((long)dividend);
long dvs = Math.abs((long)divisor);
int res = 0;
while (dvd >= dvs) {
long temp = dvs, multiple = 1;
while (dvd >= (temp << 1)) {
temp <<= 1;
multiple <<= 1;
}
dvd -= temp;
res += multiple;
}
return sign == 1 ? res : -res;
}
}
5、由于LeetCode 本身只是调用方法,并不判断算法有没有使用减法,我们看看使用除法的效率, 50 ms,击败14.19%
public class Solution {
public int divide(int dividend, int divisor) {
if(dividend == -2147483648 && divisor == -1){
return Integer.MAX_VALUE;
}
return dividend/divisor;
}
}
6、当然啦,我们看看用C语言需要多少秒 6秒
int divide(int dividend, int divisor) {
if (!divisor || ((dividend ^ divisor) == 2147483647))
return INT_MAX;
int sign = ((dividend ^ divisor) < 0) ? -1 : 1;
long dvd = labs(dividend);
long dvs = labs(divisor);
int res = 0;
while (dvd >= dvs) {
long temp = dvs, multiple = 1;
while (dvd >= (temp << 1)) {
temp <<= 1;
multiple <<= 1;
}
dvd -= temp;
res += multiple;
}
return sign == 1 ? res : -res;
}