69 Sqrt(x)
https://leetcode.com/submissions/detail/106777290/
http://www.cnblogs.com/EdwardLiu/p/3981176.html
Implement int sqrt(int x). Compute and return the square root of x.
public static void main(String[]args) { System.out.println(findSquareRoot(0.16)); // 0.4 } public static double findSquareRoot(double value) { double low = 0; double high = value; double mid = value > 1.0 ? (low + high) / 2 : 1.0; while (Math.abs(value - mid * mid) > 0.000001) { if (mid * mid == value) { return mid; } if (mid * mid > value) { high = mid; } else { low = mid; } mid = (low + high) / 2; } return mid; } }
Linkedin: 直接比较就行, 不用compare 或用newton,比较短:
public double sqrt(double x) { if (x < 0) return -1; if (x == 0 || x == 1) return x; double epsilon = 0.000001; double left = 0, right = x; if(Double.compare(x,1.0) < 0) { right = 1.0; } while (Double.compare(right-left, epsilon) > 0) { double mid = (right + left)/ 2.0; double midSqr = mid * mid; if(Double.compare(midSqr, x) == 0) { return mid;//find exact solution } else if(Double.compare(midSqr, x) < 0) { left = mid; } else { right = mid; } } return (left + right) / 2.0; }
计算x2 = n的解,令f(x)=x2-n,相当于求解f(x)=0的解,
首先取x0,如果x0不是解,做一个经过(x0,f(x0))这个点的切线(tangent line),与x轴的交点为x1。(x -intercept)
同样的道理,如果x1不是解,做一个经过(x1,f(x1))这个点的切线,与x轴的交点为x2。
and so on.
以这样的方式得到的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)的导数(differential coefficient)
,本题中为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。
输入输出都是double型,或者输入int, 输出double:或者输出int:
return (int)res;
public class Newton { public double sqrt(int x) { if (x == 0) return 0; double last = 0; double res = 1; while (res != last) { last = res; res = (res + x / res) / 2; } return res; } public static void main(String[] args){ Newton newton = new Newton(); System.out.println(newton.sqrt(3)); } }
Newton:
It is meaningless to talk about time complexity of Newton's method. It is about numerical analysis and the convergence rate is used to describe its performance, not time complexity. Thought very hard to analyze the time complexity, we know it is faster than binary search.
比较典型的数值处理的题目还有Divide Two Integers,Pow(x,n)等,其实方法差不多,一般就是用二分法或者以2为基进行位处理的方法。
这是一道数值处理的题目,和Divide Two Integers不同,这道题一般采用数值中经常用的另一种方法:二分法。基本思路是跟二分查找类似,要求是知道结果的范围,取定左界和右界,然后每次砍掉不满足条件的一半,知道左界和右界相遇。算法的时间复杂度是O(logx),空间复杂度是O(1)。代码如下:
public int mySqrt(int x) { if (x == 0 || x < 0) { return x; } int beg = 1, end = x / 2 + 1; //左边界设置为1,右边界设置为x/2+1(向上取整以确保l, r之间包含target,
否则比如x=1, l=1, r=0; x=2, l=1, r=1; 这些都漏掉了) while (beg + 1 < end) { int mid = beg + (end - beg) / 2; if (x / mid == mid) { return mid; } else if (x / mid < mid) { end = mid; } else { beg = mid; } } if (x / end == end) { return end; } else { return beg; } }
if (x / mid == mid)
//这么做,而不写成m*m <= x 其实是有深意的,是为了防止m*m的溢出。
也可以用long
long sq = (long)mid * mid;