问题:
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
说明:
被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1]。本题中,如果除法结果溢出,则返回 2^31 − 1。
解:
class Solution {
public:
int divide(int dividend, int divisor) {
//特殊情况,即会溢出的情况
if (dividend == INT_MIN&&divisor == -1) {
return INT_MAX;
}
return recursion(dividend, divisor);
}
//本题的思路是把a/b拆分成(c+d)/b,即c/b+d/b,实现起来很简单
//难就难在你得考虑一些边缘情况,比如算法中的某些中间量可能会溢出
int recursion(int dividend, int divisor) {
int temp;
int i;
int quotient;
int sign;
const int overflow = 1 << 30;//溢出判断数
bool flag;//溢出标志位,对溢出进行预测
if (-abs(dividend)>-abs(divisor)) {
return 0;
}
//对商的正负性进行判断
sign = (dividend >= 0) ^ (divisor >= 0) ? -1 : 1;
i = 0;
temp = divisor;
//待侦察数是temp,即测试temp是否即将溢出
//temp和divisor同号
//若待侦察数为负数,则(overflow&temp)=0代表即将溢出
//若为正数,则(overflow&temp)!=0代表即将溢出
//flag==1表示即将溢出
flag = (divisor < 0) ^ (bool)(overflow&temp);
//直到temp取到小于dividend的最大数
while ((!flag)&&(-abs(dividend) < -abs(temp << 1))) {
temp = temp << 1;
i++;
flag = (divisor < 0) ^ (bool)(overflow&temp);
};
//temp必须与dividend同号,由于原来temp的符号取决于divisor,故这里用sign做判断
if (sign == -1)temp = -temp;
//quotient是c/b的商
quotient = (sign>0 ? 1 : -1) << i;
//递归计算d/b的商并将两个商相加
return quotient + recursion(dividend - temp, divisor);
}
};