题目:
29、两数相除
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
整数除法的结果应当截去(truncate)其小数部分,例如:truncate(8.345) = 8 以及 truncate(-2.7335) = -2
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
解释: 10/3 = truncate(3.33333…) = truncate(3) = 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
解释: 7/-3 = truncate(-2.33333…) = -2
提示:
被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。
题解思路:
最简单的想法就是把两个数都变成正的,然后被除数不断的减去除数直到小于除数为止,最后再加上正负号。可以用异或判断两个数的正负性是否相同,而溢出的唯一可能是结果等于 2^31。当然,这种方法会在用例(-2147483648, -1) 超时。。。
不超时思路:
显然超时是因为两个数的逼近太慢。因为不能用除法,只改变被除数就必须用减法,太慢了。
所以考虑改变除数,可以不断的自加,相当于乘 2,就可以快速的逼近被除数了.
比如 (100, 2),2 不断自加最多到 64 还小于 100,那么 100 就应该先减去 64 以最快逼近,而减去 64 就相当于减去 32 个 2。
但因为不能用除法,32 不是显然得到的,所以还需要一个变量初始为 1,随着除数自加而自加,以表示等价的除数个数。
100 减去 64 后,被除数和除数变为 (36, 2),然后循环这个过程即可。
进一步的,后面明显有很多重复计算,所以可以把过程中的值 4、8、16、32、64 及等价的除数个数保存下来,再倒序遍历即可。
题解python代码:
class Solution:
def divide(self, dividend: int, divisor: int) -> int:
m, n, flag = abs(dividend), abs(divisor), int(dividend^divisor >=0)
d, w = [], 1
while n <= m:
d.append((n, w))
n += n
w += w
res = 0
for n, w in d[::-1]:
if m >= n:
m -= n
res += w
return min([-res, res][flag], 2147483647)
作者:huozhixue
链接:https://leetcode-cn.com/problems/divide-two-integers/solution/python3-jian-ji-by-huozhixue-xgo6/
来源:力扣(LeetCode)https://leetcode-cn.com/problems/divide-two-integers/