题目描述:
给你一个非负整数 x ,计算并返回 x 的 算术平方根 。
由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。
注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。
示例:
- 输入:x = 4
输出:2 - 输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842…, 由于返回类型是整数,小数部分将被舍去。
思路:
一、暴力求解,从0-num开始尝试,直到xx<=num,而(x+1)(x+1) > num,得到x。时间复杂度过高。
二、 二分查找
# 官方
class Solution:
def mySqrt(self, x: int) -> int:
l, r, ans = 0, x, -1
while l <= r:
mid = (l + r) // 2
if mid * mid <= x:
ans = mid
l = mid + 1
else:
r = mid - 1
return ans
或者:
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
if x == 0 or x == 1:
return x
left = 0
right = x
while left <= right:
mid = int((left + right) // 2)
if mid <= x / mid:
res = mid
left = mid + 1
if mid > x / mid:
right = mid - 1
return res
或者可以避免存在一个res,但是和本身二分查找的代码模板就不一样了,所以最好还是记住官方的方式。
class Solution(object):
def mySqrt(self, x):
"""
:type x: int
:rtype: int
"""
if x == 0 or x == 1:
return x
left = 0
right = x
while left <= right:
mid = (left + right) // 2
if mid == x / mid:
return mid
elif mid < x / mid and mid +1 > x / (mid+1):
return mid
elif mid < x / mid:
left = mid
elif mid > x / mid:
right = mid
时间复杂度都是一样的,就是处理和取得结果的方式不一样。
时间复杂度O(logn),空间复杂度O(1)。
同样也可以使用牛顿迭代法来解决这个问题,具体地详见链接
class Solution:
def mySqrt(self, x: int) -> int:
if x == 0:
return 0
C, x0 = float(x), float(x)
while True:
xi = 0.5 * (x0 + C / x0)
if abs(x0 - xi) < 1e-7:
break
x0 = xi
return int(x0)