使用二进制搜索查找数字的平方根
Finding the square root of a number by using binary search
我尝试使用二进制搜索来查找整数的平方根,但我无法通过一些测试用例。
我能够通过 mySqrt(4) = 2,但我无法通过 mySqrt(2147395599)
关于我搞砸的地方有什么想法吗?
public static int mySqrt(int x) {
int left = 0;
int right = x;
if(x < 2){
return x;
}
while(left < right){
int mid = left + ((right - left) / 2);
if(mid * mid == x){
return mid;
}
else if(mid * mid < x){
left = mid + 1;
}
else{
right = mid;
}
}
return left - 1;
}
因为mid * mid会溢出。您应该使用 long 以避免溢出。然后在 return 结果时将其转换回 int。
试试这个代码
public static int mySqrt(int x) {
long left = 0;
long right = x;
if(x < 2){
return x;
}
while(left < right){
long mid = left + ((right - left) / 2);
if(mid * mid == x){
return (int)mid;
}
else if(mid * mid < x){
left = mid + 1;
}
else{
right = mid;
}
}
return (int)(left - 1);
}
这就像二分查找
以下代码计算数字的 [integer] 平方根。如果号码不是
完全平方(没有整数平方根),则returns-1。它通过连续的
猜测。如果 n 为 100,它首先猜测 SO。太高?尝试更低的值 - 介于 1 之间
所以。它的运行时间是多少?
int sqrt(int n) {
return sqrt_helper(n, 1, n);
}
int sqrt_helper(int n, int min, int max) {
if (max < min) return -1; // no square root
int guess = (min + max) / 2·,
if (guess *guess == n) { // found it!
return guess;
}else if (guess * guess < n) { II too low
return sqrt_helper(n, guess + 1, max); // try higher
} else { // too high
return sqrt_helper(n, min, guess - l); //try lower
}
}
学分:破解编码面试
这是一个处理双打的版本。
- 它是递归的。
- 它计算直到达到给定的精度。
for (int i = 2; i < 10; i++) {
System.out.println("sqrt("+i+") = " + sqrt(i));
}
版画
sqrt(2) = 1.414213562373095
sqrt(3) = 1.7320508075688772
sqrt(4) = 2.0
sqrt(5) = 2.23606797749979
sqrt(6) = 2.449489742783178
sqrt(7) = 2.6457513110645907
sqrt(8) = 2.82842712474619
sqrt(9) = 3.0
public static double sqrt(double i) {
return bsqrt(i, 0, i, 0);
}
static double prec = 10E-200;
private static double abs(double d) {
return d < 0 ? -d : d;
}
private static double bsqrt(double i, double low, double high,
double last) {
double mid = (high + low) / 2;
double d = last - mid;
if (d < 0) {
d = -d;
}
if (d < prec) {
return mid;
}
double sqr = mid * mid;
if (sqr < i) {
return bsqrt(i, mid, high, mid);
} else {
return bsqrt(i, low, mid, mid);
}
}
但更好的方法是使用Newton's method。
static double prec = 10E-15;
public static double newtons(double i) {
// initial guess
double x = i / 2;
double d = i;
double nx = 0;
while (abs(d) > prec) {
nx = x - (x*x - i)/(2*x);
d = nx - x;
x = nx;
}
return nx;
}
我尝试使用二进制搜索来查找整数的平方根,但我无法通过一些测试用例。
我能够通过 mySqrt(4) = 2,但我无法通过 mySqrt(2147395599)
关于我搞砸的地方有什么想法吗?
public static int mySqrt(int x) {
int left = 0;
int right = x;
if(x < 2){
return x;
}
while(left < right){
int mid = left + ((right - left) / 2);
if(mid * mid == x){
return mid;
}
else if(mid * mid < x){
left = mid + 1;
}
else{
right = mid;
}
}
return left - 1;
}
因为mid * mid会溢出。您应该使用 long 以避免溢出。然后在 return 结果时将其转换回 int。
试试这个代码
public static int mySqrt(int x) {
long left = 0;
long right = x;
if(x < 2){
return x;
}
while(left < right){
long mid = left + ((right - left) / 2);
if(mid * mid == x){
return (int)mid;
}
else if(mid * mid < x){
left = mid + 1;
}
else{
right = mid;
}
}
return (int)(left - 1);
}
这就像二分查找
以下代码计算数字的 [integer] 平方根。如果号码不是 完全平方(没有整数平方根),则returns-1。它通过连续的 猜测。如果 n 为 100,它首先猜测 SO。太高?尝试更低的值 - 介于 1 之间 所以。它的运行时间是多少?
int sqrt(int n) {
return sqrt_helper(n, 1, n);
}
int sqrt_helper(int n, int min, int max) {
if (max < min) return -1; // no square root
int guess = (min + max) / 2·,
if (guess *guess == n) { // found it!
return guess;
}else if (guess * guess < n) { II too low
return sqrt_helper(n, guess + 1, max); // try higher
} else { // too high
return sqrt_helper(n, min, guess - l); //try lower
}
}
学分:破解编码面试
这是一个处理双打的版本。
- 它是递归的。
- 它计算直到达到给定的精度。
for (int i = 2; i < 10; i++) {
System.out.println("sqrt("+i+") = " + sqrt(i));
}
版画
sqrt(2) = 1.414213562373095
sqrt(3) = 1.7320508075688772
sqrt(4) = 2.0
sqrt(5) = 2.23606797749979
sqrt(6) = 2.449489742783178
sqrt(7) = 2.6457513110645907
sqrt(8) = 2.82842712474619
sqrt(9) = 3.0
public static double sqrt(double i) {
return bsqrt(i, 0, i, 0);
}
static double prec = 10E-200;
private static double abs(double d) {
return d < 0 ? -d : d;
}
private static double bsqrt(double i, double low, double high,
double last) {
double mid = (high + low) / 2;
double d = last - mid;
if (d < 0) {
d = -d;
}
if (d < prec) {
return mid;
}
double sqr = mid * mid;
if (sqr < i) {
return bsqrt(i, mid, high, mid);
} else {
return bsqrt(i, low, mid, mid);
}
}
但更好的方法是使用Newton's method。
static double prec = 10E-15;
public static double newtons(double i) {
// initial guess
double x = i / 2;
double d = i;
double nx = 0;
while (abs(d) > prec) {
nx = x - (x*x - i)/(2*x);
d = nx - x;
x = nx;
}
return nx;
}