求解一個整數的平方根最簡單的辦法就是用庫函數。
但是如何不用庫函數就求解呢?
1. 二分法
我們都知道5的平方根是2.236。如果要求對平方根取整,那麼就是2,我們的目的就是在{1,2,3,4,5}這樣一個數組中找到2。
這是一個典型的查找的需求,我第一時間想到的查找算法就是二分法。
設left=1,right=5,那麼第一趟的mid=3,mid^2=9,大於right,因此我們需要將right左移到mid位置來;
第二趟的left=1,right=3,mid=2,此時mid^2 = 4,基本上接近了,因此判斷一下(mid+1)^2,發現9>5,這就能斷定出5的平方根取整就是2了,直接返回。
下面是代碼的實現:
class Solution {
public:
/**
*
* @param x int整型
* @return int整型
*/
int sqrt(int x) {
// write code here
if (x<=0) return 0;
int left = 1;
int right = x;
while (left < right)
{
long mid = (left+right)/2;
if (mid*mid > x)
{
right = mid;
}
else if (mid * mid <= x && (mid+1) * (mid+1) > x)
{
return mid;
}
else
{
left = mid;
}
}
return left;
}
};
二分法的時間複雜度是O(logN),執行時間也不差:
只用了3ms。
牛頓迭代公式
用牛頓迭代公式求解平方根基本上相當於殺雞用牛刀。
我們知道平方根實際上就是這樣的一個函數:f(x)=x^2-n=0,其實就是求n的過程。
牛頓迭代公式是這樣的:
x = x- f(x)/f'(x)
所以帶入之前的f(x),我們就能知道求解平方根不過是求解一個公式罷了:
x = x - (x - n/x)/2,其中n是常數。
寫成代碼就是這樣的:
class Solution {
public:
/**
*
* @param x int整型
* @return int整型
*/
int sqrt(int x) {
// write code here
double x1=1, x2=0;
while (abs(x2-x1)> 1e-8)
{
x2=x1;//x2用於記錄上一次迭代的結果
x1 = (x1 + x/x1)/2;
}
return (int) x1;
}
};
這個效率就差點了: