Task
Implement 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
Example 1:
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.
|
Solution
暴力搜索
- 从0开始向右搜索并平方,从平方值小于x跳变到平方值大于x时即是所求点
时间复杂度
:搜到sqrt{x}时停止,时间复杂度为O(sqrt{n})
空间复杂度
:不需引入额外变量,O(1)
- 实现1(用long long避免平方溢出):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// Runtime: 20 ms, faster than 11.31% of C++ online submissions for Sqrt(x).
// Memory Usage: 5.9 MB, less than 82.79% of C++ online submissions for Sqrt(x).
class Solution {
public:
int mySqrt(int x) {
//边界情况
if(x==0 || x==1)
return x;
//使用更长的整型避免溢出
long long i=1;
while(i*i<=x)
++i;
return i-1;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
// Runtime: 64 ms, faster than 5.11% of C++ online submissions for Sqrt(x).
// Memory Usage: 6.1 MB, less than 30.77% of C++ online submissions for Sqrt(x).
class Solution {
public:
int mySqrt(int x) {
//边界情况
if(x==0 || x==1)
return x;
int i=1;
//使用除法避免溢出
while(i<=x/i)
++i;
return i-1;
}
};
|
二分查找
- 类似暴力搜索查找分界点:中点平方小于x时取右侧区间,中点平方大于x时取左侧区间。查找的终止条件是区间缩小为一个点
时间复杂度
:二分搜索,O(logn)
空间复杂度
:无额外开销,O(1)
- 实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// Runtime: 0 ms, faster than 100.00% of C++ online submissions for Sqrt(x).
// Memory Usage: 5.9 MB, less than 78.70% of C++ online submissions for Sqrt(x).
class Solution {
public:
int mySqrt(int x) {
//边界情况
if(x==0 || x==1)
return x;
//两端闭区间
int l=1,r=x;
while(l<r){
//这里使用插值形式l+(r-l)/2而非平均形式(l+r)/2,原因是相加可能溢出,相减不会
long long m=l+(r-l)/2;
//由于m是向下取整,故缩小区间时只能l=m+1,若用l=m则在l和r相邻时死循环
if(m*m<=x)
l=m+1;
else
r=m;
}
return l-1;
}
};
|
牛顿法
- 根据牛顿法迭代求根公式:$$x_{n+1}=x_n-\frac{f(x_n)}{f’(x_n)}$$
- 求$\sqrt{a}$时建立方程:$f(x)=x^2-a=0$,故牛顿公式化为:$$x_{n+1}=x_n-\frac{x_n^2-a}{2x_n}=\frac{1}{2}(x_n+\frac{a}{x_n})$$
- 根的初始值设为a,epsilon控制误差
- 实现1(用浮点型算迭代):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
// Runtime: 0 ms, faster than 100.00% of C++ online submissions for Sqrt(x).
// Memory Usage: 5.9 MB, less than 61.78% of C++ online submissions for Sqrt(x).
class Solution {
public:
int mySqrt(int x) {
//设定初始值和epsilon
double m=x;
const double eps=1e-3;
//迭代
while(abs(m*m-x)>eps)
m=(m+x/m)/2;
return static_cast<int>(m);
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
|
// Runtime: 4 ms, faster than 59.65% of C++ online submissions for Sqrt(x).
// Memory Usage: 5.9 MB, less than 61.78% of C++ online submissions for Sqrt(x).
class Solution {
public:
int mySqrt(int x) {
//从右侧逼近
long long m=x;
//不用epsilon控制误差,只要求迭代点落在根的右侧
while(m*m>x)
m=(m+x/m)/2;
return m;
}
};
|