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。

Related Topics 位运算 数学

思路:

避免直接进行乘法、除法和mod取余,以及正确处理溢出问题

暴力的解法是 以步长为1, 被除数循环减去除数,并记录减去的次数ans,当剩余的数小于除数时,ans即为结果。这种解法的时间复杂度为O(N)。

考虑指数递增步长,翻倍的步长快速逼近结果,相当于对被除数取对数,相应的复杂度为O(log2(N))。

两个数的符号,应该包括:

  1. 除数被除数同号,结果为正数
  2. 除数被除数异号,结果为负数

在除数和被除数的绝对值相等时, 以上两个结果的绝对值是相等的。

考虑溢出问题特殊情况:

  1. 被除数为最小值(左边界)时,除数为1的结果仍为最小值,除数为-1的结果为最大值。
  2. 除数为最小值时,被除数为最小值的结果为1,被除数为其他值的结果为0。
  3. 除数为0时,结果为0。

一般情况:被除数和除数的四种符号组合中,他们的结果的绝对值是相等的,因此都可以转为同号处理,又因为转为正正符号时会产生移除情况,而转为负负符号时不会出现溢出情况,因此把四种符号组合都转为负负符号处理。

打表存储指数递增步长,直到步长大于被除数时不再存储,然后逆序遍历步长表,每次结果都增加pow(2,i)。

class Solution:
    def divide(self, dividend: int, divisor: int) -> int:
        INT_MIN, INT_MAX = -2 ** 31, 2 ** 31 - 1

        # 考虑被除数是最小值的情况
        if dividend == INT_MIN:
            if divisor == -1:
                return INT_MAX
            if divisor == 1:
                return INT_MIN
        # 考虑除数是最小值的情况
        if divisor == INT_MIN:
            return 1 if dividend == INT_MIN else 0
        # 考虑除数是0的情况
        if divisor == 0:
            return 0

        # 一般情况
        # 将所有符号情况都转为负负符号处理
        flag = True  # 标记是否是同号
        if dividend > 0:
            dividend = -dividend
            flag = not flag
        if divisor > 0:
            divisor = -divisor
            flag = not flag
        # 打表
        candidates = [divisor]
        while candidates[-1] >= dividend - candidates[-1]:
            candidates.append(candidates[-1] + candidates[-1])
        print(candidates)
        ans = 0
        for i in range(len(candidates)-1, -1, -1):
            if dividend <= candidates[i]:
                ans += (1 << i)
                print(ans)
                dividend -= candidates[i]
        return ans if flag else -ans



s  = Solution()
print(s.divide(2147483647, 1))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值