给定两个整数,被除数 dividend
和除数 divisor
。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend
除以除数 divisor
得到的商。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
说明:
- 被除数和除数均为 32 位有符号整数。
- 除数不为 0。
- 假设我们的环境只能存储 32 位有符号整数,其数值范围是 [ − 2 31 -2^{31} −231, 2 31 − 1 2^{31}-1 231−1]。本题中,如果除法结果溢出,则返回 2 31 − 1 2^{31}-1 231−1。
解题思路
已给非常容易想到的解题思路就是先分析我们最后的数字是正数还是负数,我们将其全部转化为正数处理,通过divisor
的不断叠加,直到累加和超过dividend
,我们记录累加次数。最后根据结果是不是负数,加上负号即可,同时我们要考虑好边界问题。
class Solution:
def divide(self, dividend, divisor):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
res, count, divd, divs = -1, 0, None, None
pos = False if (dividend < 0) ^ (divisor < 0) else True
divd, divs = abs(dividend), abs(divisor)
if divd < divs:
return 0
mod = 2**31
while count <= divd:
count += divs
res += 1
if res == mod:
break
if pos and res == mod:
res -= 1
return res if pos else -res
但是dividend
很大divisor
很小的时候上述做法就超时了,我们只有尝试新的方法。我们可能设置一种增量式的方案,我们使每次增加的divisor
扩大两倍。我们的算法思路如下,对于例1
3 * 1 < 10
3 * 2 < 10
3 * 4 > 10
所以我们现将2
加入到结果中,然后计算我们剩余要填充的值10-2*3 = 4
。
3 * 1 < 4
3 * 2 > 4
所以我们再将1
加入到结果中,然后计算我们剩余要填充的值4 - 3 = 1
。我们此时发现剩余的值1
小于我们的divisor=3
,所以我们知道我们的结果就是1+2=3
。
对于正负数的处理我们还是按照之前的做法。代码如下
class Solution:
def divide(self, dividend, divisor):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
res, divd, divs = 0, None, None
pos = False if (dividend < 0) ^ (divisor < 0) else True
divd, divs = abs(dividend), abs(divisor)
if divd < divs:
return 0
mod = 2**31
while divs <= divd:
mul, tmp = 1, divs
while (tmp << 1) <= divd:
mul <<= 1
tmp <<= 1
res += mul
divd -= tmp
if res == mod:
break
if pos and res == mod:
res -= 1
return res if pos else -res
这种算法思路非常重要,在 Leetcode 50:Pow(x, n)(超详细的解法!!!)问题中,我们会用到同样的算法思路。
对于CPP
我们需要注意一个细节,我们使用long long
类型的话,我们需要使用labs()
,而不是abs()
。
我将该问题的其他语言版本添加到了我的GitHub Leetcode
如有问题,希望大家指出!!!