题目:
Divide two integers without using multiplication, division and mod operator.
If it is overflow, return MAX_INT.
题目很有意思,要求在不做乘法、除法、取余运算的条件下求两个除数相除的结果。
首先想到的是做减法,用一个变量标记两数相除的结果的正负(两数同号为正,异号为负),然后把除数和被除数取绝对值后做减法运算。用一个变量count表示结果,初始化为0,被除数每减除数一次,count值加一,将相减的结果作为被除数继续运算,直到被除数-除数小于0时跳出循环。算法复杂度为o(n)。代码:
class Solution {
public:
int divide(int dividend, int divisor) {
int count=0;
int mark=0;//用于标记结果为正还是为负
//把被除数转化为正数
if(dividend<0)
{
mark++;
int temp=0-dividend;
dividend=dividend+temp+temp;
}
//把除数转化为正数
if(divisor<0)
{
mark++;
int temp=0-divisor;
divisor=divisor+temp+temp;
}
while(dividend-divisor>=0)
{
dividend-=divisor;
count++;
}
if(mark==1)
{
return 0-count;
}
return count;
}
};
但是算法超时了,由于加法和减法具有相同的优先级,所以可以初步判断,仅使用加法和减法的算法是很容易超时的,必须扩展其它的运算。除加、减、乘、除、取余外,C++还有移位运算和逻辑运算,考虑移位运算:左移一位,相当于是乘2;右移一位,相当于是除以2。所以可以用移位运算来降低算法的时间复杂度。在上一个算法的基础上做优化:对除数做左移运算,得到一个再左移一位就会超过被除数的基,并记录左移的位数k,共有k个基,每个基都是2的幂次方。从最大的基开始,将被除数减去这个基,把2的k次方加到结果中,循环结束后即得到结果。算法复杂度为o(logn)。代码:
class Solution {
public:
int divide(int dividend, int divisor) {
long int count=0;
int mark=0;
//如果被除数是负数
if(dividend<0)
{
mark++;
dividend=-dividend;
}
//如果除数是负数
if(divisor<0)
{
mark++;
divisor=-divisor;
}
if(dividend==0||dividend<divisor) return 0;
int k=0;//移位位数
while(divisor<=(dividend>>1))
{
divisor=divisor<<1;
k++;
}
//减法计算
while(k>=0)
{
if(dividend>=divisor)
{
dividend -= divisor;
count+=1<<k;
}
divisor=divisor>>1;
k--;
}
if(mark==1) return -count;
return count;
}
};