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%左右。