• 5-2


    29. 两数相除

    给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。

    返回被除数 dividend 除以除数 divisor 得到的商。

    示例 1:

    输入: dividend = 10, divisor = 3
    输出: 3
    示例 2:

    输入: dividend = 7, divisor = -3
    输出: -2
    说明:

    被除数和除数均为 32 位有符号整数。
    除数不为 0。
    假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−231, 231 − 1]。本题中,如果除法结果溢出,则返回 231 − 1。

    My solution (Not Accepted: Time Limit Exceeded):

    class Solution(object):
        def divide(self, dividend, divisor):
            """
            :type dividend: int
            :type divisor: int
            :rtype: int
            """
            abs_dividend, abs_divisor = abs(dividend), abs(divisor)
            quo = 0
            
            while abs_dividend >= abs_divisor:
                abs_dividend -= abs_divisor
                quo += 1
            
            if quo > pow(2,31) - 1:
                quo = pow(2,31) - 1
                
            if dividend > 0 and divisor < 0 or dividend < 0 and divisor > 0:
                quo = -quo
            
            return quo
    

    不通过的原因:

    当被除数特别大而除数又特别小时,while循环会因循环次数过多而超时。

    但算法的整体思路是对的,因为不能使用乘除法和mod运算,这个时候就只能通过被除数与除数的加减来实现除法运算。

    一种改进方法是加速这个while循环过程,一种很好的思路如下:

    class Solution(object):
        def divide(self, dividend, divisor):
            """
            :type dividend: int
            :type divisor: int
            :rtype: int
            """
            positive = (dividend < 0) is (divisor < 0)
            dividend = left = abs(dividend)
            divisor  = div  = abs(divisor)
            Q = 1
            ans = 0
            while left >= divisor:
                left -= div
                ans  += Q 
                Q    += Q
                div  += div
                if left < div:
                    div = divisor
                    Q = 1
            if not positive:
                return max(-ans, -2147483648)
            else:
                return min(ans, 2147483647)
    

    这个算法的思路是:在每次做完减法运算时,都让div增大一倍(相当于变为原来的两倍),这样随着div不断变大(而且每次翻倍都会变得越来越大),每一轮while循环时dividend被减掉的部分就会越来越多,从而大大加快了整个减法过程的速度。

    这里需要注意的是,当div翻倍时,商因子Q也必须要翻倍。

    当div大到比dividend剩余的部分还要大时,并不意味着整个减法过程已经结束了,此时让div重新等于最初的divisor,同时Q归1,然后div和Q重新开始新一轮的翻倍过程,直至最终left < divisor。

    除此之外,还应注意两点:

    (1)对于符号的判断:

    positive = (dividend < 0) is (divisor < 0)
    

    这句话很好地将四种情况都包含了进去,例如当dividend > 0且divisor > 0时,上述代码等价于

    positive = False is False # output: positive = True
    

    (2)对于溢出情况的处理:

    使用max和min函数将输出值截断在([-2^{31} - 1, 2^{31}])之间。

  • 相关阅读:
    python如何进行内存管理的
    多进程于多线程的区别,cpu密集型适合用什么
    __new__() 与__init__()的区别
    orm的理解
    三次握手四次挥手
    HTTP、TCP、IP、协议
    mysql字段添加修改删除
    django本身提供了runserver,为什么不能用来部署(runserver与uWSGI的区别)
    django中scrf的实现机制
    django重定向是如何实现的,用的什么状态码?
  • 原文地址:https://www.cnblogs.com/tbgatgb/p/11113878.html
Copyright © 2020-2023  润新知