'''
leetcode 29. 两数相除
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
'''
class Solution:
def divide(self, dividend: int, divisor: int) -> int:
if dividend==0:# 被除数为0,商为0
return 0
if divisor==1:# 除数为1,直接返回被除数
if dividend<0:
return max(dividend,-2**31)
else:
return min(dividend,2**31-1)
if divisor==-1:# 除数为1,直接返回被除数
if dividend>0:
return max(0-dividend,-2**31)
else:
return min(0-dividend,2**31-1)
if dividend>0 and divisor>0:
return min(self.helper(dividend,divisor),2**31-1)
if dividend>0 and divisor<0:
return max(0-self.helper(dividend,0-divisor),-2**31)
if dividend<0 and divisor<0:
return min(self.helper(0-dividend,0-divisor),2**31-1)
if dividend<0 and divisor>0:
return max(0 - self.helper(0-dividend, divisor), -2 ** 31)
def helper(self,a,b):
'''
其中a和b都是正整数,求商,实际上是求被除数中能够最多减去多少个除数,得到的结果小于除数
:param a:
:param b:
:return:
使用循环做减法,统计做减法的次数,显然会超时。这里引入位运算的技巧
任何整数(这里只考虑正整数)都可以表示成2的整数幂的线性组合,即被除数可以这样表示
如45 / 4 除数45,被除数4
用temp统计输出的商
101101
首先将4左移k位数,(这里巧妙地运用了位运算来实现乘法,将4左移一位就是将4放大2倍)
使得4*(2**k)的结果是能让k取得最大并且该数值不超过45的,得到k=3,说明45至少包含(2**3)=8 个4 temp+=8
再将45-4*8=13,继续搜索下一个k值,注意这次搜索时不需要从k=1开始搜索,而是从k=3(继上次计算得到的k)开始搜索,k-=1
得到k=1 13-4*(2**1)=5 即13中至少包含2**k=2个4 temp+=2
再将13-4*2=5 从k=0开始搜索,发现k=0满足要求,temp+=(2**0)=10+1=11
再将5-4=1 1<4 终止循环
'''
output=0# 返回结果,商
if a<b:
return 0
if a==b:
return 1
k=0# 意味着a至少大于b*(2**0)=b
c=b
result=0
while (c < a):
c = c << 1
k += 1
k-=1
result+=1<<k
# print('here',result,k)
a-=b<<k
while(a>b):
# 找到最大的k,使得b*(2**k)<a
temp=b<<k
while(temp>a):
temp=temp>>1
k-=1
a-=temp
result+=1<<k
return result
if __name__=="__main__":
print(Solution().divide(45,4))
print(Solution().divide(7,-3))
assert Solution().divide(10,3)==3
assert Solution().divide(7,-3)==-2