力扣刷题笔记:29.两数相除(倍增法、很容易理解的代码、不使用任何的乘除运算)

题目:

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)

力扣刷题笔记:29.两数相除(倍增法、很容易理解的代码、不使用任何的乘除运算)_第1张图片

作者: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/

你可能感兴趣的:(刷题笔记,leetcode,python)