题目描述:实现 int sqrt(int x) 函数。
计算并返回 x 的平方根,其中 x 是非负整数。
由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。
示例 1:
输入: 4
输出: 2示例 2:
输入: 8
输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。
方法一:二分查找法
由于非负整数 x(当 x ≠ 0 时) 的平方根一定是落在区间 [1, x/2 + 1],所以左右边界分别取 1 和 x/2 + 1,而不分别取 0 和 x,这样可缩小查找范围。
为了防止 mid * mid 太大而发生整型溢出,取 mid 跟 x/mid 比较。
说明
右边界 right 取 x/2 + 1,而不取 x/2,这是因为当 x = 1 时,right 如果取 x/2,由于 x/2 会向下取整使得 x/2 = 0,此时 left = 1 大于 right = 0,以至于直接跳出循环,导致 1 的平方根为 0,这明显是错误的。
当 x = 0 时,以下代码也适合。
补充说明
如果没有出现 mid == x / mid 的情况,最后到底是 return right 还是 return left?
- 可以通过调试得出;
- 循环结束的条件是 left = right + 1,示例中提示了当 x = 8,其平方根是 2,有点类似于向下取整的意思,所以是 return right 。
1 | class Solution { |
复杂度分析
- 时间复杂度:O(logx),即为二分查找需要的次数。
- 空间复杂度:O(1)。
执行结果:通过
- 执行用时:2 ms, 在所有 Java 提交中击败了45.78%的用户
- 内存消耗:35.7 MB, 在所有 Java 提交中击败了21.41%的用户
方法二:牛顿迭代
迭代的方法是用泰勒级数近似
记住牛顿法的公式:xi = 0.5 * (x0 + C / x0) ,反复迭代到x0 与 xi 相差的绝对值小于1e-7即可
1 | class Solution { |
复杂度分析
- 时间复杂度:O(logx),此方法是二次收敛的,相较于二分查找更快。
- 空间复杂度:O(1)
执行结果:通过
- 执行用时:1 ms, 在所有 Java 提交中击败了100.00%的用户
- 内存消耗:35.6 MB, 在所有 Java 提交中击败了20.45%的用户
变形:精确到xxx小数
1 | // import java.text.DecimalFormat; |