代码仓库:Github | Leetcode solutions @doubleZ0108 from Peking University.
- 解法1(爆内存): 依次循环直到
i
2
<
t
a
r
g
e
t
<
(
i
+
1
)
2
i^2 < target < (i+1)^2
i2<target<(i+1)2
- 这里如果用乘法容易int溢出,用除法就会避免
- 改进(T57% S83%):可以从1~x/2二分查找降复杂度
- 解法2(T80% S98%): 牛顿迭代法
【牛顿迭代法】
平方根相当于求解 x 2 = n ⟺ f ( x ) = x 2 − n x^2 = n \iff f(x) = x^2-n x2=n⟺f(x)=x2−n的解,牛顿迭代法从一个很大的数开始,不断做函数切线,取切线于x轴交点不断迭代
x i x_i xi处的切线方程 f ( x i ) + f ′ ( x i ) ( x − x i ) = 0 f(x_i) + f'(x_i)(x-x_i) = 0 f(xi)+f′(xi)(x−xi)=0
解方程得 x = x i 2 + n 2 x i x = \frac{x_i^2 + n}{2x_i} x=2xixi2+n
终止条件是 x , x i x, x_i x,xi足够近,对于整数问题就是判断这两个数是不是差了1
或者可以通过泰勒函数展开来求近似解,本质是一样的
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
if x < 2: # 0, 1
return x
# 解法2
t = x
while t > x//t:
t = (t**2 + x) // (2*t)
return t
def otherSolution(self, x):
if x < 2:
return x
# 解法1: 直接顺序解会爆内存
for i in range(1, x//2+1):
if i*i <= x and (i+1)*(i+1) > x:
return i
# 解法1 改进
i, j = 1, x//2+1
while i<=j:
mid = (i+j)//2
if mid**2 <= x:
i = mid + 1
else:
j = mid - 1
return (i+j)//2
# 标准的牛顿法
root = x/2
for _ in range(20): # 迭代20次
root = (1/2) * (root + (x/root))
return root