问题描述:
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
也就是不用乘、除、取模运算实现两个数的除法。
问题求解:
因为不能用乘除法和取余运算,我们只能使用位运算和加减法。
任何一个整数可以表示成以2的幂为底的一组基的线性组合,即num=a_0*2^0+a_1*2^1+a_2*2^2+...+a_n*2^n
。基于以上这个公式以及左移一位相当于乘以2,我们先让除数左移直到大于被除数之前得到一个最大的基。然后接下来我们每次尝试减去这个基,如果可以则结果增加2^k,然后基继续右移迭代,直到基为0为止。因为这个方法的迭代次数是按2的幂直到超过结果,所以时间复杂度为O(logn)。
#include <iostream>
#include<cstdlib>
#include<limits.h>
using namespace std;
class Solution {
public:
int divide(int dividend, int divisor) {
//if(dividend==0 || divisor==0) return 0;
int sign=1;//存储最后结果的符号
if(dividend<0) sign *= -1;
if(divisor<0) sign *= -1;
long long tmp_dividend=dividend;//long long类型来存储,防溢出
long long tmp_divisor=divisor;
long long abs_dividend=abs(tmp_dividend);//获取绝对值
long long abs_divisor=abs(tmp_divisor);
//if(abs_dividend < abs_divisor) return 0;
long long result=0;
while(abs_dividend >= abs_divisor)
{
long long base=abs_divisor;
unsigned int add=1;//2的方幂2^k,增加的步长,设置为unsigned int是关键!!!!!!!!!
while(base<<1 <= abs_dividend)
{//(1)先让除数左移(乘2)直到大于被除数之前得到一个最大的基
add = add<<1;
base = base<<1;//除数一直乘2,直到得到最大基
}
//(2)每次尝试减去这个基,如果可以则结果增加2^k
abs_dividend -= base;
result += add;
}
return (sign==-1)?sign*result:(result<=INT_MAX?result:INT_MAX);
}
};
int main()
{
Solution s;
int dividend=-2147483648;
int divisor=-1;
int res=s.divide(dividend,divisor);
cout<<res<<endl;
return 0;
}