Leetcode两数相除
题目描述
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
来源:力扣(LeetCode)题目链接
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
题解
注意:
- 被除数和除数均为 32 位有符号整数
- 除数不为 0
- 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [ − 2 31 −2^{31} −231, 2 31 − 1 2^{31} − 1 231−1]。本题中,如果除法结果溢出,则返回 2 31 − 1 2^{31} − 1 231−1
题解一(基于快速乘法思想)
class Solution {
public:
int divide(int dividend, int divisor) {
if(! dividend) return 0;
//diviend有可能 = INT_MIN 如果此时除数为1或-1 若int 溢出 = -1
long long res = 0;
//diviend有可能 = INT_MIN 转成int 溢出 = -1
long long dividend_abs = abs((long long)dividend);
long long divisor_abs = abs((long long)divisor);
if (dividend_abs < divisor_abs) return 0;
long long t = divisor_abs, p = 1;
while (dividend_abs > (t << 1)) {
t <<= 1;
p <<= 1;
}
res += p + divide(dividend_abs - t, divisor_abs); //递归
//判断符号
if ((dividend ^ divisor) < 0) res = -res;
//题目特别说明
return res > INT_MAX ? INT_MAX : res;
}
};
题解二(倍增)
class Solution {
public:
int divide(int dividend, int divisor) {
// 考虑被除数为最小值的情况
if (dividend == INT_MIN) {
if (divisor == 1) {
return INT_MIN;
}
if (divisor == -1) {
return INT_MAX;
}
}
// 考虑除数为最小值的情况
if (divisor == INT_MIN) {
return dividend == INT_MIN ? 1 : 0;
}
// 考虑被除数为 0 的情况
if (dividend == 0) {
return 0;
}
if(1 == divisor) return dividend;
//记录符号
int sign = (dividend ^ divisor)>=0 ? 1 : -1; //若符号相同则1,符号不同则-1
// 转成负数
int newDividend = dividend>0 ? -dividend : dividend;
int newDivisor = divisor>0? -divisor:divisor;
// 倍增
int ans = 0;
while(1){
int a = newDividend, b = newDivisor;
int count = 1;
if(a > b) break;
while(b >= a-b){
b += b;
count <<= 1;
}
newDividend -= b;
ans += count;
}
return ans*sign;
}
};