• 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
    
    Knowledge, like candlelight, can illuminate a person and countless people.
  • 相关阅读:
    struct中的字段顺序的大小
    go web之CSRF库的使用方式和实现原理
    Go进阶23:Go指针返回值的劣势(译)
    16 Transformer 的编码器(Encodes)——我在做更优秀的词向量
    13 MultiHead SelfAttention(从空间角度解释为什么做多头)
    07 预训练语言模型的下游任务改造简介(如何使用词向量)
    11 SelfAttention相比较 RNN和LSTM的优缺点
    1401 位置编码公式详细理解补充
    08 ELMo模型(双向LSTM模型解决词向量多义问题)
    09 什么是注意力机制(Attention )
  • 原文地址:https://www.cnblogs.com/xiaoqiangink/p/14367044.html
Copyright © 2020-2023  润新知