Я решил этот вопрос по коду 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))
. Обычно для алгоритмов мы говорим, что они равны O(log(n))
, когда вход делится на 2 на каждой итерации, но здесь я умножаю divisor
на 2 Q<<= 1
на каждой итерации, поэтому на каждом шаге я делаю больший шаг к решению. Очевидно, что если dividend
совпадает с большим divisor
, мой алгоритм будет быстрее. Точно так же, чем больше dividend
для того же divisor
, тем медленнее время выполнения.
Я предполагаю, что уравнение, управляющее временем выполнения этого алгоритма, в основном имеет форму O (делитель / делитель) (это деление) с некоторыми журналами, чтобы учесть мое умножение Q
на 2 на каждом шаге Q <<= 1
... я не могу понять что именно.
EDIT:
Когда я впервые опубликовал вопрос, алгоритм которого я разместил ниже, ответ Алена Мериго основан на этом алгоритме. Разница между версией сверху и той, что выше, заключается в том, что мои дивиденды никогда не опускаются ниже 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