java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.youkuaiyun.com/grd_java/article/details/123063846 |
---|
1. 数学
解题思路:时间复杂度O( 1 1 1),空间复杂度O( 1 1 1) |
---|
通过自然对数换底,将其换为其它两个数学操作: x = x 1 2 = e l n x 1 2 = e 1 2 l n x \sqrt{x} = x^\frac{1}{2} = e^{lnx^\frac{1}{2}} = e^{\frac{1}{2}lnx} x=x21=elnx21=e21lnx
代码 |
---|
class Solution {
public int mySqrt(int x) {
if (x == 0) return 0;
//Math.exp(a)表示对a做自然对数,求lna
int ans = (int) Math.exp(0.5 * Math.log(x));
//计算机无法存储浮点数精确值,指数函数和对数函数都返回浮点数,运算过程会有偏差
//当求Integer.MAX_VALUE等较大值,例如x = 2147395600,Math.exp(0.5 * Math.log(x));的计算结果与正确值46340差10^-11
//此时我们取值时,会得到46339这个错误的结果,也就是取值后相差1
//所以如果求出的数+1相乘后 <= 原来的数,就返回ans+1.否则说明没有偏差到取整差1,返回ans本身
return (long) (ans + 1) * (ans + 1) <= x ? ans + 1 : ans;
}
}
2. 二分查找法
解题思路:时间复杂度O( l o g 2 x log_2x log2x),空间复杂度O( 1 1 1) |
---|
- x的平方根的整数部分ans就是 k 2 k^2 k2 <= x的最大k值.我们对k进行二分查找,从而提高查找效率
- 我们知道x的一半x/2的平方是 >= x的, 因此k的范围就是[0,x/2],我们对这个范围进行二分查找
代码 |
---|
class Solution {
public int mySqrt(int x) {
if(x==1) return 1;
int l = 0, r = x/2;//二分查找的范围
int ans = -1;//保存结果
while (l <= r) {//如果还有的查就继续
int mid = l + (r - l) / 2;//获取l和r的mid
if ((long) mid * mid <= x) {//如果当前mid比x的平方根小
ans = mid;//保存mid
l = mid + 1;//从mid右边区间继续
} else {//如果mid比x平方根大
r = mid - 1;//从mid左边区间继续找
}
}
return ans;
}
}
3. 牛顿迭代法
解题思路:时间复杂度O( l o g 2 x log_2x log2x),空间复杂度O( 1 1 1) |
---|
- 这是底层求平方根的库函数的常见实现方法。原理是高数中的微积分中的知识,但是属于超纲题
- 核心是通过迭代,也就是泰勒级数,不断逼近函数的零点。也就是找函数零点的一种方法
代码 |
---|
class Solution {
/**牛顿迭代法,可以算出小数,高数中的导数求零点的进阶知识
* 例如 求根号2,我们先随便猜近似值4(猜多少都无所谓,越接近,越省时间),然后根据公式a = (a+x/a)/2
* 迭代第一次 a = (4+2/4)/2 = 2.25
* 第二次 a = (2.25+2/2.25)/2 = 1.56944....
* 第三次 a = (1.56944...+2/1.56944...)/2 = 1.42189.....
* 计算次数越多,越精确,但是如果你要用java算,不要超过精度
* 比如我们可以精确到1e-7(10的-7次方精度0.0000001)
* 如何判断精确到这个精度呢
* 如果 |上一次的值-这次迭代的值|的绝对值 <1e-7 就说明精度到位了
* 注意这个公式不能给0用
* @param x
* @return
*/
public int mySqrt(int x) {
if(x==0) return 0;//公式不能给0用
//a是每次迭代结果,b是上一次迭代结果
double a = x,b = x;
while(true){
//牛顿迭代公式,(当前迭代结果a+原值x/当前迭代结果a)/2
a = (a+x/a)*0.5;//牛顿迭代,迭代次数越多精度越高
//编程,确定精度方法,两次迭代结果的差的绝对值<指定精度,就说明精度到位了
if(Math.abs(b-a)<1e-7) break;
b = a;//否则b记录这次迭代结果
}
return (int)a;//题目要求,必须是整数
}
}