05 August 2008
Implement
.1
int sqrt(int x)
Compute and return the square root of x, where x is guaranteed to be a non-negative integer.
Since the return type is an integer, the decimal digits are truncated and only the integer part of the result is returned.
Example 1:
1
2
Input: 4
Output: 2
Example 2:
1
2
3
4
Input: 8
Output: 2
Explanation: The square root of 8 is 2.82842..., and since
the decimal part is truncated, 2 is returned.
求平方根,保证输入是正数,向下返回值。
1)用二分搜索来在[0,x]之间找平方根,找到一个不大于目标值的数;
2)使用牛顿迭代法,这个主要是逼近法求方程的根(http://www.cnblogs.com/AnnieKim/archive/2013/04/18/3028607.html),这里是求x^2的解,因此方程f(x) = x^2 - n, 相当于求解f(x)=0的解,如图所示
首先取x0,如果x0不是解,做一个经过(x0,f(x0))这个点的切线,与x轴的交点为x1。
同样的道理,如果x1不是解,做一个经过(x1,f(x1))这个点的切线,与x轴的交点为x2。
以此类推。
以这样的方式得到的xi会无限趋近于f(x)=0的解。
判断xi是否是f(x)=0的解有两种方法:
一是直接计算f(xi)的值判断是否为0,二是判断前后两个解xi和xi-1是否无限接近。
经过(xi, f(xi))这个点的切线方程为f(x) = f(xi) + f’(xi)(x - xi),其中f’(x)为f(x)的导数,本题中为2x。令切线方程等于0,即可求出xi+1=xi - f(xi) / f’(xi)。
继续化简,xi+1=xi - (xi2 - n) / (2xi) = xi - xi / 2 + n / (2xi) = xi / 2 + n / 2xi = (xi + n/xi) / 2。
二分法搜索合适的数,模板写法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Solution {
public int mySqrt(int x) {
if (x <= 1) {
return x;
}
int left = 0, right = x;
while (left + 1 < right) {
int mid = left + (right - left) / 2;
int temp = x / mid;
if (temp >= mid) { // 等于时还不能停,因为是地板除法,temp*mid可能比x小(有更大的备选),所以要挪动left
left = mid;
} else {
right = mid;
}
}
if (x / right >= right) { // 先检查right是否符合,因为right更大
return right;
}
return left;
}
}
牛顿迭代法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Solution {
public int mySqrt(int x) {
if (x == 0) {
return 0;
}
double last = 0;
double result = 1;
while (result != last) {
last = result;
result = (result + x / result) / 2;
}
return (int)result;
}
}