Leetcode 29:两数相除(超详细的解法!!!)

给定两个整数,被除数 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 2311]。本题中,如果除法结果溢出,则返回 2 31 − 1 2^{31}-1 2311

解题思路

已给非常容易想到的解题思路就是先分析我们最后的数字是正数还是负数,我们将其全部转化为正数处理,通过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

如有问题,希望大家指出!!!

你可能感兴趣的:(Problems,leetcode解题指南)