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

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

一、引言

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

给定一个 正整数 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. 有效的完全平方数

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





相关文章
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
【每周一坑】三国演义中谁的存在感最强 +【解答】暴力计算圆周率
当然,精确统计是比较复杂的,比如同样是刘备,可以是 刘备、玄德、刘豫州、刘皇叔、使君、先主、备,而同样的 主公、丞相、将军 这些称谓在不同语境下指的又是不同的人。这里我们就只粗略算个大概即可,统计哪些个名字出现次数最多。你可以尽量让结果更接近实际值。
|
10月前
【每日一道智力题】之如何最快的找到最轻的砝码
【每日一道智力题】之如何最快的找到最轻的砝码
112 0
|
11月前
四道好题分享(看似简单,但是棘手)
四道好题分享(看似简单,但是棘手)
68 0
|
11月前
|
机器学习/深度学习 算法 索引
算法步步为营(1)-两数之和
给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出和为目标值 target 的那两个整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。可以按任意顺序返回答案。
60 0
|
11月前
|
存储 算法 vr&ar
算法步步为营(02)-两数之和
两个非空链表,表示两个非负整数。它们每位数字都是逆序存储,且每个节点只能存储一位数字。 将两个数相加,并以相同形式返回一个表示和的链表。除了数字 0 之外,这两个数都不会以 0 开头。
77 0
|
算法 JavaScript 前端开发
日拱算法:双指针解“判断子序列”,除夕快乐~
算法继续,本篇带来的是非常典型的一道题:“判断子序列”,采用的是双指针的解法~
|
机器学习/深度学习 算法
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
<<算法很美>>——(六)——回溯算法(下)—N皇后问题
|
算法 安全
当我们谈论算法我们在谈论什么:由疫情核酸检测想到的分治算法(Divide-and-Conquer)
解释一下病毒核酸检测的原理,检测人员提取小区居民的鼻腔拭子或者咽拭子(就是用一根棉签在咽喉处或者鼻腔深处刮取一些分泌物),然后将该棉签放入试剂盒,以病毒独特的基因序列检测靶标,通过PCR扩增,使我们选择的这段靶标DNA序列指数级增加,每一个扩增出来的DNA序列,都可与我们预先加入的一段荧光标记探针结合,产生荧光信号,扩增出来的靶基因越多,累计的荧光信号就越强。说白了就是试剂盒荧光反映变色越强烈,说明病毒体量和活性越强。
当我们谈论算法我们在谈论什么:由疫情核酸检测想到的分治算法(Divide-and-Conquer)
|
算法 搜索推荐 Windows
从荷兰国旗问题出发,详解快速排序算法的原理
从荷兰国旗问题出发,详解快速排序算法的原理
120 0
|
算法 Java 测试技术
大厂面试题:求根号2简单?高级算法你肯定不会
大厂面试题:求根号2简单?高级算法你肯定不会
185 0
大厂面试题:求根号2简单?高级算法你肯定不会