新版剑指offer第一题,不允许用乘除符号来实现除法。思路:
1. 将被除数与除数都转换为负数,便于统一计算;
2. 当被除数大于除数时,继续循环比较判断被除数是否大于除数的2倍、4倍、8倍、2^k倍;
3. 如果被除数最多大于除数的 $2^k$ 倍,那么将被除数减去除数的2^k倍;
4. 将剩余的被除数重复前面的2、3步骤,由于每次将除数翻倍,因此时间复杂度是$O(logN)$。
class Solution {
public:
int divide(int dividend, int divisor) {
//为了避免被除数为0x80000000(即INT_MIN),除数为-1时,商为INT_MAX+1,会造成整形溢出
//因为最小的整数是-2^32,而最大的整数是2^31 - 1
if (dividend == INT_MIN && divisor == -1) return INT_MAX;
//利用异或运算符,两个数如果同号则结果为正数,异号则结果为负数
int flag = (dividend > 0) ^ (divisor > 0) ? -1 : 1;
if (dividend > 0) dividend = -dividend; //统一转换为负数
if (divisor > 0) divisor = -divisor;
unsigned res = divideCode(dividend, divisor);
return flag == 1 ? res : -res;
}
int divideCode(int dividend, int divisor)
{
int res = 0;
//当被除数大于除数时一直循环,注意此时两个数都是负数,所以越小即是越大
while (dividend <= divisor)
{
int value = divisor; //存一下当前循环的除数,注意除数始终是不变的
unsigned quotient = 1; //quotient:商
//0xc0000000表示INT_MIN的一半
while (value >= 0xc0000000 && dividend <= value + value)
{
quotient += quotient; //除数与商每次循环加倍
value += value;
}
res += quotient; //更新结果与被除数的值
dividend -= value;
}
return res;
}
};