剑指leetcode—x的平方根

题目描述:实现 int sqrt(int x) 函数。 计算并返回 x 的平方根,其中 x 是非负整数。 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:

输入: 4
输出: 2

示例 2:

输入: 8
输出: 2
说明: 8 的平方根是 2.82842…,
由于返回类型是整数,小数部分将被舍去。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sqrtx
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

根据题意不可以使用Math库的sqrt函数,所以需要去研究该sqrt函数是怎么实现的

方法一:

二分法

假设x(非负整数)的平方根为sqrts,那么sqrts一定是在区间【1,,x】之间的数

算法思想

  1. 定义l=1,r=x,ans=0(结果值),进入循环while(l<=r)求得中位数mid=(r+l)/2;
  2. 如果mid的平方小于x,记录ans=mid,那么继续对区间【mid+1,r】处理,直到l>r结束
  3. 如果mid的平方大于x,那么继续对区间【l,mid-1】处理
  4. 如果mid的平方等于x,那么直接返回mid

如果x是一个可以直接开平方没有小数部分的数,例如,9,16,25,程序运行时最后会直接进入第四步,如果是一个15,,开平方有小数部分的,需要设置一个ans变量来记录变换区间时的值,当到3*3这一步时,9<15,所以ans=3,左区间加一为4,此时l>r,循环结束。

java代码实现

public int mySqrt(int x) {

    int L = 1, R = x;

    int ans = 0; 

    while (L <= R) {

        int mid = (L + R) / 2;

        int square = mid * mid;

        if (square == x) {

            return mid;

        } else if (square < x) {

            ans = mid; //存起来以便返回

            L = mid + 1;

        } else {

            R = mid - 1;

        }

    }

    return ans;

}

如果x = Integer.MAX_VALUE 的话,下边两句代码是会溢出的。

int mid = (L + R) / 2;

int square = mid * mid;

所以建议使用long变量,
使用long类型变量,注意返回时,要强制转型为int返回

class Solution{
    
public int   mySqrt(int  x) {

    long  L = 1, R = (long)x;

    long  ans = 0; 

    while (L <= R) {

        long  mid = (L + R) / 2;

        long  square = mid * mid;

        if (square == x) {

            return (int)mid;

        } else if (square < x) {

            ans = mid; //存起来以便返回

            L = mid + 1;

        } else {

            R = mid - 1;

        }

    }

    return (int)ans;

}
}

也可以不使用long变量

int mid = L + (R - L) / 2;等价于 int mid = (L + R) / 2;

只不过前者不会溢出数据类型

int div = x / mid;

如果修改为这句,那么if语句以及else if中的条件判断也需要进行修改

if(div==mid)
return mid;
。。。。。。

方法二:

牛顿法

牛顿迭代法是一种可以用来快速求解函数零点的方法,用n表示待求出平方根的那个整数,那么n的平方根就是函数f(xn)=x^2-n的零点,利用牛顿迭代通式(无限逼近零点)可得
在这里插入图片描述

java代码实现:

class Solution{
	public int mySqrt(int x){	
		if(x==0)
		return 0;
double c=x,x0=x;
while(true)
{
	double xi=0.5*(x0+c/x0);
//x0和xi都是x^2-n=0的近似零点解,但是需要的解的要求是:求出的前后的两个解的差很小才能满足程序的输出要求
	if(Math.abs(x0-xi)<1e-7){
		break;
		}
	x0=xi;
}
return (int)x0;
	}
}

另一种思考角度利用牛顿迭代法也可以解决

class Solution{
    
public int mySqrt(int n) {

    double t = n; // 赋一个初值
//直到找到一个解x=t满足,函数x^2-n<=0.1
    while (Math.abs(t * t - n) > 0.1) {

        t = (n / t + t) / 2.0;

    }

    //先对t进行四舍五入 

    int ans = (int) Math.round(t); 

    //判断ans^2是否超出n

    if ((long) ans * ans > n) {
	//超出了ans-1就是答案,ans自减
        ans--;

    }

    return ans;

}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Devin Dever

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值