文章目录
更多LeetCode题解
Given two integers dividend
and divisor
, divide two integers without using multiplication, division and mod operator.
Return the quotient after dividing dividend
by divisor
.
The integer division should truncate toward zero.
Example 1:
Input: dividend = 10, divisor = 3
Output: 3
Example 2:Input: dividend = 7, divisor = -3
Output: -2
Note:
- Both dividend and divisor will be 32-bit signed integers.
- The divisor will never be 0.
- Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [ − 2 3 1 , 2 3 1 − 1 ] [−2^31, 2^31−1] [−231,231−1]. For the purpose of this problem, assume that your function returns 2 3 1 − 1 2^31−1 231−1 when the division result overflows.
Solution
- 首先想到的是减法,毫无疑问TLE
- 看完解法后写出以下算法,将
divisor
不断左移,减少减法次数。然而这是个虎头蛇尾的算法,它在divisor
大于dividend
之后再次用dividend
去减原始的divisor
毫无疑问会TLE。
class Solution {
public:
int divide(int dividend, int divisor) {
int sign = (dividend > 0) ^ (divisor > 0) ? -1 : 1;
dividend = abs(dividend);
divisor = abs(divisor);
int c_divisor = divisor;
int res = 1;
dividend -= divisor;
while (dividend >= divisor) {
dividend -= divisor;
divisor <<= 1;
res <<= 1;
}
while (dividend >= c_divisor) {
dividend -= c_divisor;
res += 1;
}
}
};
divisor
倍增,直到最后一个不大于dividend
的divisor
为止,从dividend
中将它减掉,再次重复这个过程,将divisor
再次从原始值开始倍增。这个解法AC。
class Solution {
public:
int divide(int dividend, int divisor) {
if (dividend == 0) return 0;
int sign = (dividend > 0) ^ (divisor > 0) ? -1 : 1;
long dvd = abs(dividend), dvs = abs(divisor), res = 0;
while (dvd >= dvs) {
long temp = dvs, m = 1;
while (temp << 1 <= dvd) {
temp <<= 1;
m << 1;
}
dvd -= temp;
res += m;
}
return sign * res;
}
};
- 但是以上代码存在一个问题,它使用了
long
类型,而题目的note里说了是这是不被允许的。思考一下什么情况会溢出?dividend==INT_MIN
,对它取模是无法用32位存储的。divisor==INT_MIN
temp << 1 > INT_MAX
,temp左移之后可能大于INT_MAX。
代码修改如下:
class Solution {
public:
int divide(int dividend, int divisor) {
if (dividend == 0) return 0;
int sign = (dividend > 0) ^ (divisor > 0) ? -1 : 1;
//2.
if (divisor == INT_MIN) {
if (dividend == INT_MIN)
return 1;
else
return 0;
}
//1.
if (dividend == INT_MIN) {
if (divisor == 1)
return INT_MIN;
else {
dividend += 1;
int res = subDivide(dividend, divisor);
if (dividend + 1 == abs(divisor) && divisor != -1) {
res += 1;
}
return sign * res;
}
}
return sign * subDivide(dividend, divisor);
}
int subDivide(int &dvd, int dvs) {
dvd = abs(dvd);
dvs = abs(dvs);
int res = 0;
while (dvd >= dvs) {
int temp = dvs, m = 1;
//3.
while (INT_MAX - temp >= temp && temp << 1 <= dvd) {
temp <<= 1;
m <<= 1;
}
dvd -= temp;
res += m;
}
return res;
}
};