题目描述:
给定两个整数,被除数 dividend 和除数 divisor。将两数相除,要求不使用乘法、除法和 mod 运算符。
返回被除数 dividend 除以除数 divisor 得到的商。
示例 1:
输入: dividend = 10, divisor = 3
输出: 3
示例 2:
输入: dividend = 7, divisor = -3
输出: -2
说明:
被除数和除数均为 32 位有符号整数。
除数不为 0。
假设我们的环境只能存储 32 位有符号整数,其数值范围是 [−2^31, 2^31 − 1]。本题中,如果除法结果溢出,则返回 2^31 − 1。
我的方法
此题的困难在于转换为加减法处理时,会超时。能够想到的一个提高处理效率的方式是:用移位。但移位如何应用于除数为奇数的情况,这又是一个问题。
class Solution(object):
def divide(self, dividend, divisor):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
cnt=0 #商
op=1 #符号
if (dividend>0 and divisor<0) or (dividend<0 and divisor>0):
op=-1
# 溢出的情况
if dividend==-0x80000000 and divisor==-1:
return 0x7FFFFFFF
# 取绝对值
dividend,divisor=abs(dividend),abs(divisor)
while dividend>=divisor:
dividend-=divisor
cnt+=1
res=cnt if op>0 else -cnt
return res
别人的方法
看了别人的方法,果然是采用的移位思想,我感觉挺精妙的。具体处理步骤如下:
- 采用移位的方式,大致确定商所在的区间。即用被除数 除以
2^31, 2^30 ……, 2^0
,从大到小依次尝试。 - 直到n=k时满足
被除数/2^n≥除数
。因为一开始n=31,被除数除以2^31,结果一般会小于除数。当n逐渐减小时,才会满足以上不等式。 - 上述被除数除以2^n,事实上等效于右移n位。
- 此时,最终结果可以表示为
(被除数-2^k*除数)/除数+2^k
。通过移位操作有效的降低了计算量。 - 递归的处理此问题。
效果竟然如此之好,有点不可思议:显示详情,执行用时 : 24 ms, 在Divide Two Integers的Python提交中击败了100.00% 的用户。内存消耗 : 11.7 MB, 在Divide Two Integers的Python提交中击败了39.42% 的用户
class Solution(object):
def divide(self, dividend, divisor):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
n=31
op=1
if (dividend>0 and divisor<0) or (dividend<0 and divisor>0):
op=-1
dividend,divisor=abs(dividend),abs(divisor)
if dividend<divisor:
return 0
while n>=0:
if (dividend>>n)>=divisor:
break
n-=1
diff=(dividend-(divisor<<n))
res=self.divide(diff,divisor)+(1<<n) if op==1 else -(self.divide(diff,divisor)+(1<<n))
return 0x7FFFFFFF if res>0x7FFFFFFF else res