LeetCode 69. Sqrt(x) 解题报告
题目描述
Implement int sqrt(int x).
Compute and return the square root of x.
示例
没有给出。
限制条件
没有明确给出。
解题思路
这道题很虐心,我首先用的是牛顿迭代法解题,但是一直在2147395600和214739599这两个数出问题,于是改成用二分法,然而,还是载在这两个数据上,通过艰苦卓绝地debug调试才终于过了,下面分别讲解这两种解法,并贴出AC的代码。
二分法:
二分法就是不断更新结果所属的上界和下界来逼近结果,比如求9的平方根,一开始设置结果的界限为[0, 9],中间点取整后是4(
⌈(0+9)÷2⌉=4
),因为
42=16>9
,表示上界可以更新为4,此时界限为[0, 4],中间点取整后2(
⌈(0+4)÷2⌉=2
),因为
22=4<9
,证明下界可以更新为2,所以界限为[2,4],不断重复上述步骤,最后会得到接近或等于9的平方根的结果。
具体实现中需要根据题目调整参数,比如数据类型需要为long long,循环的结束条件是low > high以及返回的是(low + high) / 2。请见下面代码1.
牛顿迭代法:
牛顿迭代法同样是通过迭代来逼近结果的解法。它将求平方根的问题转化为求
f(x)=x2−a(其中a是待求平方根的数)与x轴交点
,显而易见,
x=a√
就是其中一个解。对
f(x)
求导,得到
f′(x)=2x
,表明
f(x)曲线上的每一点的切线斜率是2x
。
接下来结合下图对迭代过程进行讲解:
首先假设一个解为
xi
,对应的就是
f(xi)
,当然这个解不是结果,所以需要寻找下一个更靠近结果的点
xi+1
,而寻找
xi+1
的一个简单方法就是在
(xi,f(xi))
处作切线,取切线与
x
轴的交点。
由于
上式得到就是递推的公式,不断使用该公式得到 x 直到
下面贴出来的牛顿迭代法代码是大神的解答代码,真是简洁优雅。
代码
二分法
class Solution {
public:
int mySqrt(int x) {
if (x < 2)
return x;
long long low = 0, high = x, result = 0;
while(high >= low) {
result = (low + high) / 2;
if (result * result > x)
high = result - 1;
else if (result * result < x)
low = result + 1;
else
break;
}
return (low + high) / 2;
}
};
牛顿迭代法
class Solution {
public:
int mySqrt(int x) {
long r = x;
while (r * r > x)
r = (r + x / r) / 2;
return r;
}
};
总结
这道题花了很长时间,以前我不知道求平方根有二分法和牛顿迭代法,所以花了时间去理解这两种算法,原理很容易理解,但是实现时却出现了各种问题,需要耐心调试。
通过这道题我学会了牛顿迭代法,并知道了二分法的另一个应用,感觉收获很大,下周继续加油~