文章目录
- 题目描述
- 解题方法
- 倍增
- java代码
- 复杂度分析
题目描述
给你两个整数,被除数 dividend
和除数 divisor
。将两数相除,要求 不使用 乘法、除法和取余运算。
整数除法应该向零截断,也就是截去(truncate)其小数部分。例如,8.345
将被截断为 8
,-2.7335
将被截断至 -2
。
返回被除数 dividend
除以除数 divisor
得到的 商 。
注意:假设我们的环境只能存储 32 位 有符号整数,其数值范围是 [−231, 231 − 1]。本题中,如果商 严格大于 231 − 1 ,则返回 231 − 1 ;如果商 严格小于 -231 ,则返回 -231 。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = 3.33333.. ,向零截断后得到 3 。
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = -2.33333.. ,向零截断后得到 -2 。
提示:
- -231 <=
dividend, divisor
<= 231 - 1 divisor != 0
解题方法
倍增
按照 a a a 和 b b b 都是正数的情况说明。我们设 x × b < = a x \times b<=a x×b<=a 且 2 × x × b > a 2 \times x \times b>a 2×x×b>a,如果求 k × b = a k \times b = a k×b=a,那么 k k k 一定满足 x < = k < 2 x x <= k < 2x x<=k<2x。
按照 d i v i d e n d dividend dividend 和 d i v i s o r divisor divisor 都是正数的情况说明。我们可以利用上面的方式不断对 d i v i s o r divisor divisor 倍增,同时记录倍增数 m u l mul mul( m u l mul mul 即为 k k k,初始为1),当 d i v i d e n d − m u l × d i v i s o r < m u l × d i v i s o r dividend− mul \times divisor < mul \times divisor dividend−mul×divisor<mul×divisor时, d i v i d e n d = d i v i d e n d − m u l × d i v i s o r dividend = dividend− mul \times divisor dividend=dividend−mul×divisor,答案追加 m u l mul mul。然后重复利用上面的方式计算倍增数 m u l mul mul, d i v i d e n d dividend dividend 不断缩小,答案追加 m u l mul mul。直到 d i v i d e n d < d i v i s o r dividend < divisor dividend<divisor 时,即求出最终结果。
由于负数的表示范围更大,可以将 d i v i d e n d dividend dividend 和 d i v i s o r divisor divisor 转化为负数,再利用倍增的思想计算结果。具体代码如下。
java代码
public int divide(int dividend, int divisor) {
if (dividend == Integer.MIN_VALUE && divisor == -1) {
return Integer.MAX_VALUE;
}
// 记录结果正负
boolean flag = (dividend < 0) ^ (divisor < 0);
// 将a和b设置为负数,a和b符号相同时方便辗转相减(如果设置为正数,dividend或divisor有一方是Integer.MIN_VALUE时,a或b转化为正数会越界)
int a = (dividend < 0) ? dividend : -dividend;
int b = (divisor < 0) ? divisor : -divisor;
//记录结果
int result = 0;
// a > b时,a / b = 0
while (a <= b) {
// 记录倍增倍数
int mul = 1;
// 用temp临时记录b
int temp = b;
// 当temp + temp >= a时,mul倍增,temp倍增(之所以用减法是因为temp相加可能会超过整形范围)
while (a - temp <= temp) {
mul += mul;
temp += temp;
}
// a减去倍增后的temp,剩余的a再与b相除
a -= temp;
result += mul;
}
return flag ? -result : result;
}
复杂度分析
时间复杂度:
O
(
l
o
g
2
N
)
O(log^2N)
O(log2N),其中
N
N
N 表示 32 位整数的范围。最坏情况系下倍增的次数为
O
(
l
o
g
N
)
O(logN)
O(logN) +
O
(
l
o
g
N
2
)
O(log\frac {N} {2})
O(log2N) +
O
(
l
o
g
N
4
)
O(log\frac {N} {4})
O(log4N) + …… +
O
(
l
o
g
N
N
)
O(log\frac {N} {N})
O(logNN),故渐进复杂度为
O
(
l
o
g
2
N
)
O(log^2N)
O(log2N)。
空间复杂度:
O
(
1
)
O(1)
O(1)。
- 个人公众号
- 个人小游戏