这道题目要求是不使用乘法、除法和mod运算符来除两个整数,题目看起来比较简单,但是存在一些坑,在这里简单记录一下做题时所碰到的坑。
一、实现除法运算,最简单的方法是用被除数对除数做减法,最后得到的减法次数就是所求的数,但是这样做,运算时间很长,容易超时;
二、后来在网上查资料看到了另一种解法:
- 每次将除数扩大两倍(左移一位),当扩大到一个临界值(左移n位),该临界值小于被除数,但是左移一位大于被除数,此时所得的中间商为pow(2,n);
- 将被除数减去该临界值,用所得的差值进行步骤1的过程,假设此时左移m位,则中间商为pow(2,m);
- 重复步骤2,直到差值小于除数;
- 最后所求的商为pow(2,n)+pow(2,m)+……
这个解法的运算效率比方法二高很多,由于运算的数据范围是[pow(-2,31),pow(2,31)-1],在实现过程中需要注意边界问题,具体实现代码如下:
class Solution {
public:
int divide(int dividend, int divisor) {
long long int data = 0;
long long int count = 0;
int rst = 0;
int flag = (dividend < 0) ^ (divisor < 0) ? -1 : 1;
if (!divisor || ((dividend == INT_MIN) && (divisor == -1)))
return INT_MAX;
long long int dividend1;
long long int divisor1;
if (dividend < 0)
{
if (dividend == -2147483647 - 1)
{
dividend1 = -2147483647 * (-1);
dividend1 = dividend1 + 1;
}
else
dividend1 = dividend * (-1);
}
else
dividend1 = dividend;
if (divisor < 0)
{
if (divisor == -2147483647 - 1)
{
divisor1 = -2147483647 * (-1);
divisor1 = divisor1 + 1;
}
else
divisor1 = divisor*(-1);
}
else
divisor1 = divisor;
if (dividend1 < divisor1)
{
rst = 0;
}
else
{
while (dividend1 >= divisor1)
{
count = 0;
data = divisor1;
while (dividend1 >= data<<1)
{
count++;
data = data <<1;
}
rst += pow(2, count); //需要注意,当count为31时,rst为 -2147483648,在商为负数输出的情况下,不需要转为负数了
dividend1 = dividend1 - pow(2,count)*divisor1;
}
}
//return flag == 1 ? rst : -rst;
if(flag == 1)
{
rst = rst;
}
else
{
if(rst>INT_MIN)
rst = -rst;
else if(rst == INT_MIN)
rst = INT_MIN;
}
return rst;
}
};
注意的点:
- 在vs中进行测试时,当输入为 -2147483648,使用INT_MIN或直接写为 -2147483647-1;
- 将 -2147483648转为正数赋给一个long long int类型的数据时,需要写成 (-2147483647)*(-1)+1,不然转换结果不对,不知道为啥,可能和编译器的处理方式有关吧;
- 在leetcode网页上编译程序时,对于有返回值的函数,返回值写在条件判断语句外面,虽然所有情况在条件判断语句中都有写,但还是会有报错:-Werror = return type。