暴力循环已死,牛顿迭代法称王

简介: 暴力循环已死,牛顿迭代法称王

一、引言

今天在做力扣每日一题中,有一道题为:

给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。
进阶:不要 使用任何内置的库函数,如  sqrt 。

大名鼎鼎的求平方根,传说中的牛顿迭代法,本篇来看一下具体是怎么进行实现的吧!

二、牛顿迭代法

牛顿迭代法又称为牛顿-拉弗森方法,实际上是由牛顿、拉弗森(又是一个被牛顿大名掩盖的家伙)各自独立提出来的

牛顿-拉弗森方法提出来的思路就是 利用切线是曲线的线性 逼近这个思想。

牛顿、拉弗森们想啊,切线多简单啊,研究起来多容易啊,既然切线可以近似于曲线,我直接研究切线的根不就成了。

如图所示:

6130b16d6bc943e894568a0f30e4dfe3.png

对于上述函数的根来说,我们知道:x = 0

如果用牛顿迭代法怎么进行计算呢?

  • F(x) = x * x
  • F’(x) = 2 * x


db56f86fd7ca425d99e9f0c0b6ef938a.png

首先,牛顿迭代法会找到一个点,比如 x0 ,从 x0 向曲线做直线,交于点 A,做点 A 的切线交于点 x1

这样的话,我们可以得到三个点:x1、x0、A

设A点坐标为 (x0,x0 * x0)、x1点坐标为 (x1, 0)

通过A点和x1点的坐标,可以得出该线的斜率:K = (x0 * x0) / (x0 - x1)


化简得知:


x0 - x1 = ( x0 * x0) / K

x0 - x1 = F(x0) / F’(x0)

x0 - x1 = x0 / 2

x1 = x0 / 2

我们再以 x1 点做上面相同的操作,得到:

  • x2 = x1 / 2

我们无限制的进行上述操作,最终会得到一个公式:Xn+1 = Xn / 2

当无线次的迭代时,我们的 x 值会趋于0

三、平方根

我们上面说到,对于 F(x) = x * x,最终得到的结果为:Xn+1 = Xn / 2

我们想,对于平方根来说:x * x = num

可不可以转化一下,比如:F(x) = x * x - numF'(x) = 2 * x,求这个函数的交点

利用上述我们说的牛顿迭代法,我们可以得知:

F1 点为(x0,x0 * x0 - num)x1 点为(x1,0)

则:

  • K = (x0 * x0 - num) / (x0 - x1)
  • x0 - x1 = (x0 * x0 - num) / K
  • x0 - x1 = F(x0) / F’(x0)
  • x0 - x1 = x0 / 2 - num / (2 * x0)
  • x1 = x0 / 2 + num / (2 * x0)
  • 将x1、x2两点同样进行迭代,得到:x2 = x1 / 2 + num / (2 * x1)

得出式子:Xn+1 = Xn / 2 + num / 2 * Xn

简单来说,选中某个x的初始值,无限进行迭代,最终找到其平方根

F(x) = x * x - num 凸函数的性质,最终的结果应该是:x = sqrt(num)

我们最开始的 x 可以直接取值为 num,因为 num >= sqrt(num)

一般来说,可以判断相邻两次迭代的结果的差值是否小于一个极小的非负数,一般可以取 1e-6 或者 1e-7

四、代码实现

  public boolean isPerfectSquare(int num) {
        if(num == 1){
            return true;
        }
        double ans = num;
        double dir = num;
        while(ans * ans - dir >= 1e-6){
            ans = ans / 2 + dir / (2 * ans);
        }
        int x = (int)ans;
        return x * x == num;
    }

1d70a50edb7640de9be77b45c2908c15.png

五、总结

简单来说,牛顿迭代法通过不断的进行迭代,逐渐趋近于某个目标值

题目一:367. 有效的完全平方数

有兴趣的小伙伴可以去做一下,目前来说对于这种 平方根 题目,面试官最想听到的就是 牛顿迭代法,反手给其一波推理过程,直接抬走面试官。





相关文章
|
8月前
|
C语言
青蛙跳台阶:我如何得知它是一道斐波那契数列题?——应用题破题“三板斧”(一)
这篇内容介绍了C语言学习中的经典例题——斐波那契数列,强调了解题思路的重要性。斐波那契数列是一个数列,其中每个数是前两个数的和。文章指出,很多类似题目,如“青蛙跳台阶”,实质上都在考察斐波那契数列的实现。文中提供了斐波那契数列的定义、代码实现和递归与非递归的思路,并鼓励读者从问题中分析出解题模型,而非直接套用已知方法。此外,还提及了一道相关题目“矩形覆盖问题”,以供进一步练习。
66 0
|
8月前
|
机器学习/深度学习 算法 测试技术
青蛙跳台阶:我如何得知它是一道斐波那契数列题?——应用题破题“三板斧”(二)
这篇内容是关于解题策略的,主要介绍了在面对应用题时可以采用的“三板斧”方法:举例、模拟和找规律。通过一个走楼梯的例子详细解释了这三个步骤如何运用。首先,举例将抽象问题具体化,比如走5级台阶有几种方式。其次,通过模拟不同情况,例如思考走每一步的可能,发现递归或循环的模式。最后,通过找规律归纳出一般性的解决方案,这里发现走台阶问题与斐波那契数列相关。文章还提到了一个拓展案例——矩形覆盖问题,同样可以用类似的方法分析。总的来说,文章强调了解题过程中理解和转化问题的重要性,以及通过训练提升这方面能力。
66 0
|
算法 网络架构
代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果
代码随想录算法训练营第三十三天 | LeetCode 1005. K 次取反后最大化的数组和、134. 加油站、135. 分发糖果
65 0
校门外的树(三种解法,非直接暴力)
校门外的树(三种解法,非直接暴力)
|
算法
【每日挠头算法题】Acwing 756. 蛇形矩阵 —— 巧妙解法
【每日挠头算法题】Acwing 756. 蛇形矩阵 —— 巧妙解法
151 0
【每日挠头算法题】Acwing 756. 蛇形矩阵 —— 巧妙解法
|
存储 算法
【趣学算法】贪心算法、海盗古董装船问题
贪心选择是指原问题的整体最优解可以通过一系列局部最优的选择得到,也就是先做出当前最优的选择,将原问题变为一个相似却规模更小的子问题,而后的每一步都是当前最优的选择。这种选择依赖于已做出的选择,但不依赖于未作出的选择。
再学一道算法题:危险的七(约瑟夫环问题)
这是一道学校acm基地招新的题    我之前也写过一道有几分相似的题,所以比赛的时候写的快一点,但是也没有完全理解,容易自己都搞混,有朋友问我的解题思路时,我也讲错,这大可能是自身能力不够,这提醒我还需要继续提升自己的实力
再学一道算法题:危险的七(约瑟夫环问题)
|
机器学习/深度学习 算法 搜索推荐
算法渣-递归算法
之前的排序算法 《快速排序》 与 《归并排序》 都使用了递归手法,如果不能理解递归,那分治思想类算法实现就难以理解
122 0
|
算法
查找算法——俄罗斯轮盘赌算法(看谁运气不好)
查找算法——俄罗斯轮盘赌算法(看谁运气不好)
657 0
查找算法——俄罗斯轮盘赌算法(看谁运气不好)
|
算法 Java 索引
【蓝桥杯】KMP算法难以理解只能硬背?东哥这个思路让你10分钟彻底掌握
KMP 算法(Knuth-Morris-Pratt 算法)是一个著名的字符串匹配算法,效率很高,说实话,有点复杂。
【蓝桥杯】KMP算法难以理解只能硬背?东哥这个思路让你10分钟彻底掌握