【发布时间】:2019-05-22 20:59:56
【问题描述】:
我解决了这个 leetcode 问题 https://leetcode.com/problems/divide-two-integers/ 。目标是在不使用乘法或除法运算符的情况下获得dividend 除以divisor 的商。这是我的解决方案:
def divide(dividend, divisor):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
sign = [1,-1][(dividend < 0) != (divisor < 0)]
dividend, divisor = abs(dividend), abs(divisor)
res = 0
i = 0
Q = divisor
while dividend >= divisor:
dividend = dividend - Q
Q <<= 1
res += (1 << i)
i+=1
if dividend < Q:
Q = divisor
i = 0
if sign == -1:
res = -res
if res < -2**31 or res > 2**31 -1:
return 2**31 - 1
return res
所以我无法分析此解决方案的时间复杂度。我知道应该是O(log(something))。通常对于算法,当输入在每次迭代中除以 2 时,我们说它们是 O(log(n)),但这里我在每次迭代时将 divisor 乘以 2 Q<<= 1,因此在每一步中,我都会朝着解决方案迈出更大的一步。显然,如果dividend 与更大的divisor 相同,我的算法会更快。同样,dividend 越大,divisor 的运行时间就越慢。
我的猜测是,控制该算法运行时间的方程基本上是 O(dividend/divisor) (duh 那是除法)的形式,其中包含一些日志来说明我在每个步骤中将 Q 乘以 2 @987654334 @...我不知道到底是什么。
编辑:
当我第一次发布问题时,我发布的算法是下面的问题,Alain Merigot 的答案是基于该算法。上面的版本和上面的版本之间的区别是我从来没有让我的红利低于 0,从而导致更快的运行时间。
def divide(dividend, divisor):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
sign = [1,-1][(dividend < 0) != (divisor < 0)]
dividend, divisor = abs(dividend), abs(divisor)
res = 0
i = 0
tmp_divisor = divisor
while dividend >= divisor:
old_dividend, old_res = dividend, res
dividend = dividend - tmp_divisor
tmp_divisor <<= 1
res += (1 << i)
i+=1
if dividend < 0:
dividend = old_dividend
res = old_res
tmp_divisor >>= 2
i -= 2
if sign == -1:
res = -res
if res < -2**31 or res > 2**31 -1:
return 2**31 - 1
return res
【问题讨论】:
-
我们根据操作数的位数来考虑复杂度,并且我们知道每次迭代都会产生一点结果。最坏的情况是除数 = 1 并且被除数为 2^31+k。在这种情况下,有 32 (n) 次迭代,复杂度是线性的。
-
这其实很有道理,你介意扩展一下这个想法,以便我能理解吗?谢谢
标签: python-3.x algorithm bitwise-operators division bit-shift