LeetCode29-两数相除

2018/11/29

我们学校125周年校庆

普校同庆

学校给发了免费的鱼丸汤

虽说鱼丸真的不咋地,哈哈哈哈

但真的挺开心的

感受到了学校浓厚的人文气息

不多说了,直接上图

                              


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。

这一题刚开始看的时候一脸懵逼,乘法和mod取余都不能用,那还做个屁啊(弱鸡吐槽,大佬们看着乐乐就行哈)最后突然灵光一闪,想到了用加法来做,就是每次将被除数以固定的倍数增加(此处就是它自身),以此来逼近除数,它增加的次数就是商。Perfect 瞬间觉得自己是个天才,不费九牛二虎之力很快就把程序编出来了,兴冲冲的放到答题板上run 我还在期待着它的执行效率有多快,谁知道显示的是大写的Red:超出时间限制。大家先看代码吧!

代码如下:

class Solution:
    # 将被除数以步长为自身的增加去逼近除数
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        """
        if divisor == 0:
            return 2 ** 31 - 1
        shang = 0
        flag = 1 if divisor * dividend > 0 else -1
        divisor = abs(divisor)
        dividend = abs(dividend)
        divisor_copy = divisor
        # 每次迭代,步长shang都是1倍增长
        while divisor <= dividend:
            shang += 1
            divisor += divisor_copy
        if -2**31 <= flag*shang <= 2**31 - 1:
            return flag*shang
        else:
            return 2**31 - 1


if __name__ == "__main__":
    dividend = -7
    divisor = 2
    result = Solution().divide(dividend, divisor)
    print(result)

不知道大家看完之后有没有知道是哪儿出问题了导致执行时间过长,如果很快就知道了,那说明你的算法涵养是真的不错了。其实问题就是当除数过大,被除数过小时,此时消耗时间过长。比如22229999999除以2,如果按照我上面的程序来每次增加2,这得算到什么时候啊!就算是计算机也hold不住(当然我这儿的计算机指代的是我们穷学生用的普通配置的笔记本),所以我们接下来要优化的就是被除数每次迭代的步长值,就拿上面那个例子来说:如果每次迭代的步长值也能呈倍数增加,那可以减少很多不必要的计算了,时间自然也是大大的缩短了。那说到这儿很多笔友就会问了:你说的倒是头头是道,那怎么实现呢?各位别急,我刚开始也是想不通,后来在网上看到了一位大佬写的,觉得茅塞顿开。核心思想就是:使用神器位操作Bit Operation

过程:将一个数左移一位也就相当于将这个是乘以2,我们将除数左移一位也就是相当于将他乘以2,任何一个整数都可以用二进制的形式来表示,用二进制表示的最小单位是1,而这里使用的是最小的单位是这个除数,这样就可以移动的方式来观察被除数中到底有多少个除数,最后将这些数做和,返回就OK了。

代码如下:

class Solution:
    def divide(self, dividend, divisor):
        """
        :type dividend: int
        :type divisor: int
        :rtype: int
        """
        #首先这一句就很python,postive 为true是符号相同
        positive = (dividend < 0) is (divisor < 0)
        dividend, divisor = abs(dividend), abs(divisor)
        res = 0
        #检查dividend是否大于divisor
        #如果还小于则进行小精度的逼近dividend
        while dividend >= divisor:
            temp, i = divisor, 1
            #增大逼近dividend的步伐
            #i不断增加, temp不断减少
            while dividend >= temp:
                #经过上一句的判断,所以dividend还大于0
                dividend -= temp
                #商要加对应的i
                res += i
                #倍数相应的要增加
                i = i<<1
                print("i", i)
                #目前的值也要不断的增加
                temp = temp<<1
                print("temp", temp)
        #判定正负号
        if not positive:
            res = -res
        return min(max(-2147483648,res), 2147483647)


if __name__ == "__main__":
    dividend = -2147483648
    divisor = 1
    result = Solution().divide(dividend, divisor)
    print(result)

最后的执行效率也算是中上等吧,在70%左右。

 

猜你喜欢

转载自blog.csdn.net/weixin_36431280/article/details/84646634
今日推荐