LeetCode 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。


思路:

既然不能用乘除法,可以换种思路,除法乘法其实就是变相的加减法。

我们可以从被除数减去除数,记录经历多少个multiple因子,即为我们需要的结果

方法一:

位运算辅助,核心思想是通过减法,同时倍增倍减因子模拟实现除法功能。

class Solution(object):
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        """
        res = 0
        MIN_INT, MAX_INT = -2147483648, 2147483647  # [−2**31, 2**31−1]
        flag =  1 if dividend ^ divisor >= 0 else -1 #异或用来判断正负
        dividend = (dividend + (dividend>>31))^(dividend>>31) #取绝对值
        divisor = (divisor + (divisor>>31))^(divisor>>31) #取绝对值
        res = 0
        while dividend >= divisor:
            cur,multiple = divisor,1
            while dividend >= cur:
                dividend -=cur
                res +=multiple
                multiple <<=1 
                cur <<=1
        if flag<0:
            res = ~res +1 #取相反数
        return min(max(MIN_INT, res), MAX_INT)

方法二:

记录一下Orust题解的思路。
两种方法同一种思路,只不过不是用位运算进行操作。

递归:

class Solution(object):
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        """
        MIN_INT, MAX_INT = -2147483648, 2147483647  # [−2**31, 2**31−1]
        flag = 1                                    # 存储正负号,并将分子分母转化为正数
        if dividend < 0: flag, dividend = -flag, -dividend
        if divisor < 0: flag, divisor  = -flag, -divisor 
        
        def div(dividend, divisor):                 
            if dividend < divisor:
                return 0
            cur = divisor
            multiple = 1
            while cur + cur < dividend:             # 用加法求出保证divisor * multiple <= dividend的最大multiple
                cur += cur                          # 即cur分别乘以1, 2, 4, 8, 16...2^n,即二进制搜索
                multiple += multiple
            return multiple + div(dividend - cur, divisor)
        res = div(dividend, divisor)

        res = res if flag > 0 else -res             # 恢复正负号
        
        if res < MIN_INT:                           # 根据是否溢出返回结果
            return MIN_INT
        elif MIN_INT <= res <= MAX_INT:
            return res
        else:
            return MAX_INT

迭代:

class Solution(object):
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        """
        MIN_INT, MAX_INT = -2147483648, 2147483647
        flag = 1
        if dividend < 0:
            flag, dividend = -flag, -dividend
        if divisor < 0:
            flag, divisor = -flag, -divisor
        res = 0
        while dividend >= divisor:
            cur = divisor    #第一次是cur = divisor
            multiple = 1
            while cur+cur < dividend:
                cur += cur   # 直接比较divisor x 2(加快比较速度)
                multiple += multiple   # 保留divisor的倍数,也就是我们需要累加的商
            dividend -= cur    # dividend 减除数divisor 进行下一轮while
            res += multiple   
        res = res if flag >0 else -res  #还原商的正负
        if res < MIN_INT:
            return MIN_INT
        elif res > MAX_INT:
            return MAX_INT
        else:
            return res
posted @ 2021-02-03 14:56  萧蔷ink  阅读(82)  评论(0编辑  收藏  举报