先来点废话。觉得自己写的博客质量太低了,一是代码健壮度很多地方还有待优化,其次是有些题的整体思路不够宽阔(没有做到一题多解)。做题总是追求AC, AC完了后就不管了。所以在从现在反省一下,要保证每道题的质量,详细讲解我搜索到的所有解法。
本人一直在努力地积累Leetcode上用Python实现的题,并且会尽力讲清每道题的原理,绝不像其他某些博客简略地带过。
如果觉得讲的清楚,欢迎关注。
题目:
给定两个整数,被除数 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。
思路:这道题一开始我用加减的方式去模拟乘除做的,结果很容易TLE。所以这道题我们要去想如何加快我们的加和速度。
网上的其他很多解大概都是用位运算符的。
总结一下这道题思路:1.通过位运算模拟*2,加快扩大divisor的速度
2.通过整除或者其他方式。
位运算最快,整除等属于第二梯队。
先来看位运算解法:
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
#目前的值也要不断的增加
temp = temp<<1
#判定正负号
if not positive:
res = -res
return min(max(-2147483648,res), 2147483647)
总的来说,这思路就是不断将dividend减少的while循环。总体循环分两层。外层用来控制最终跳出循环情况,同时它可以初始化逼近的间隔。内层是用来加快逼近速度的,你可以看到它是不断的2倍2倍的翻。所以总体思路和我一开始叠加的想法差不多,只不过它用了逼近的方法去提高自己的效率。所以这也是一种二分查找。
还有一种挺牛逼的解法,利用了python的特性:
class
Solution
:
def
divide
(
self
,
dividend
,
divisor
):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
sign
=
1
if
(dividend
<
0
)
==
(divisor
<
0
)
else
-
1
x, y
=
abs
(dividend),
abs
(divisor)
if
x
<
y:
return
0
if
x
==
y:
return
sign
#比较强大的思路以及优美的写法
#构建一个生成器,这个生成器以divisor为步长
arange
=
range
(y, x, y)
alen
=
len
(arange)
#判断临界情况
if
arange[
-
1
]
+
y
<=
x:
alen
+=
1
#正负
if
sign
==
-
1
:
alen
=
-
alen
return
min
(alen,
2
**
31
-
1
)
接着是与上面思路类似的解法(题目没说不能用整除,但我觉得还是有钻空子的嫌疑,因为其他语言除法和整除是一样的符号)
class Solution:
def divide(self, dividend, divisor):
"""
:type dividend: int
:type divisor: int
:rtype: int
"""
i = abs(dividend)//abs(divisor)
if dividend > 0 and divisor < 0 or dividend < 0 and divisor > 0:
i *= -1
max_limit = 2**31 - 1
if i < -2**31 or i > max_limit:
return max_limit
return i
总的来说,这期的精华还是二分查找。2个while的控制让我拍案叫绝。二分不一定是分,也可能是不断扩大2倍。学习了