在刷leetcode 69 .x的的平方根的时候, 题解中提到了这个牛顿迭代法, 我觉得这个是一个好的算法,在很多求值的领域都可以用上,因为满足牛顿迭代法的会收敛于一个值,这里有点想二分法查找,但是个人感觉比二分法查找更快
首先我们来看一下这道题目吧:
class Solution {
public int mySqrt(int x) {
}
}
其实我们Math中有一个Math.sqrt()方法就是用来求开方的(int) Math.sqrt(x);
,但是这样子做,我们就没必要学算法了啊。
题解中提到了一个牛顿迭代法,我觉得特别微妙
大概思路就是这样的:
- 我们先假设x开平方之后的值就为x(这里大胆假设,例如2开平方之后的值假设为4,其实这已经很离谱了,但是牛顿迭代法可以让这个假设的值不断收敛于最真实的值)
- 因为求开方的函数就是f(x)=x^2-a,(这里a就是我们要求开方的数字,这里是2),因为是函数的原因,所以函数上每一个点的斜率都是f(x)’=2x
- 那么T点的值,是不是比4的值更加接近于我们要求的2的开方的值?
- 那么我们B的值怎么求呢?
- 我们已经知道斜率是8了,斜率的定义就是tana,也就是对边/邻边
- 所以A/B=k的,所以B=A/k,也就是B=f(x)/2x
- 所以T点的值为:x-B=x-f(x)/2x
- 我们得到T点的值之后,我们又可以用相同的方法得到下一个点的值,这样就可以无限收敛于某一个点了
动图来了:
听他们说这是数学分析里面的内容,但是由于我们只是学习了高数就没了的,对这方面的知识不够,所以数学还是重要的啊,有时候数学不是不重要,是你没想到能够用上它。
所以这道题的代码就是这样子写了
package Leetcode;
/**
*@time 2020年5月8日:上午11:16:06
*@author Weirdo
*@version 1.0
**/
public class N69 {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
int a;
public int mySqrt(int x) {
a=x;//假设我们开方之后的值就是x本身,让他自动收敛
if(x==0)
return 0;
return (int)sqrt(x);
}
private double sqrt(double x) {
double res = (x+(a/x))/2;
if(res==x) {
return x;
}else {
return sqrt(res);
}
}
}
leetcode题解原文:牛顿迭代法