一、题目描述
> 🚥【问题分析】
这个问题有很多处理方法, 比如暴力枚举法,二分查找法。但今天介绍一个大家可能没有接触过的方法——牛顿迭代法。牛顿迭代法是求方程根的一种方法,其基本的思想就是:切线是曲线的线性逼近。通过这样不断的逼近,我们最终可以得出方程的解。
大家千万不要被牛顿的大名给吓到了,今天所讲的内容只要学过导数和三角函数就是有手就行。
二、方法介绍
①方法介绍
B是方程的零点,我们取零点附近一点A,过点A做曲线的切线与X轴交于D点。过点D做x轴的垂线,得到与曲线的交点E
我们继续过点E做曲线的切线,通过不断重复上述过程,最终使得切线与x轴的交点不断接近与零点。我们由此就可以得出零点的近似解。
是不是很简单,那我们继续往下看。
②递推关系式
我们可以从三角函数入手,以α角为例,我们可以得出以下的关系式:
③迭代结束的判断
不断迭代的过程中,x是不断趋向于零点的,同时“Xc”也是和“Xd”也是不断接近的,当Xc-Xd < 1E-6时,我们可以近似的认为此时Xc就等于零点值。
④牛顿迭代法的局限
当然牛顿迭代法也不是万能的,仅举以下几个例子:参考文章1.对于这种凸函数反而越切越远
2.初始点选择不恰当,导致最终得出的解不是我们的目标解
3.陷入循环震荡之中
我们也不做什么具体的数学总结,大家在使用牛顿迭代法时首先预画图观察能否不断逼近零点。我想这样就能处理很多的问题了。接下来我们回到力扣题。
三、代码实现
int mySqrt(int num)
{
if(num == 0)
return 0;
double x0 = (double)num;
while(1)
{
double x1 = x0 / 2 + num / x0 / 2;
if(x0 - x1 < 1E-7)
break;
x0 = x1;
}
return (int)x0;
}
1.方程构建
由x ^ 2 = num我们可以构造出方程 f(x) = x^2 - num。转化为牛顿迭代法求零点问题
2. 初始点的选择
以num作为我们的初始点,经画图检验后一定会不断趋近于零点。
3.迭代关系式
从下图中我们可以看出 f(X0) / (x0 - X1) = f’(X0);
4.迭代结束的标志
当x0不断接近零点时,x0和x1也是不断接近的。当x0 - x1 < 1E-7时可以近似认为得到零点。
5.时间复杂度分析:
(证明过程来源Leetcode)
所以对于这道题目而言,这是一个logn时间复杂度的算法