力扣算法题(二分)-69.x的平方根

一、题目

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

示例 1:

输入:x = 4
输出:2

示例 2:

输入:x = 8
输出:2
解释:8 的算术平方根是 2.82842..., 由于返回类型是整数,小数部分将被舍去。

二、题解

        对于这道题,最开始没什么思路,在查看题解并分析后总结如下:

1、二分查找

        思路:二分查找即将n个元素分成两部分,每次将中间值mid的平方与目标值x相比较

        1、若mid的平方等于x,mid即为结果,直接返回目mid;

        2、若mid的平方大于x,那么x的平方根应该在[left,mid-1]范围内,right=mid-1,在左侧继续进行二分查找;

        3、若mid的平方小于x,那么x的平方根应该在[mid+1,right]范围内,left=mid+1,在右侧继续进行二分查找。代码如下:

class Solution {
public:
    int mySqrt(int x) {
        int left=0,right=x,ans=-1;//左指针,右指针,存放临时结果
        while(left<=right){       //left==right时的值是有效的
            int mid=left+(right-l)/2;
            if((long long)mid*mid<=x){//向右二分
                left=mid+1;
                ans=mid;
            }else{                     //向左二分
                right=mid-1;
            }
        }
        return ans;
    }
};

        分析:时间复杂度:O(logx),空间复杂度:O(1)。由于所有运算均是整数运算,不会存在误差。

        2、牛顿迭代法:

        思路:求算术平方根即令x^2=C,即可以转化为函数f(x)=x^2-C=0求零点问题,从x0开始迭代(以防迭代到负的平方根)。每次过(x0,f(x0))作f(x)的切线,切线与x轴的交点x1比x0更接近零点,此时再过(x1,f(x1))作f(x)的切线,切线与x轴交点x2比x1更接近零点,依次类推,直到迭代的两个值差值小于1e-7表示两个点非常接近,此时可以认为这是算术平方根。计算x0和x1关系如下:

代码如下:

class Solution {
public:
    int mySqrt(int x) {
        if(x==0) return 0;
        double x0=x,c=x;
        while(true){
            double x1=(x0+c/x0)/2;由切线方程可以得出
            if(abs(x0-x1)<1e-7){//确定循环结束条件
                break;
            }
            x0=x1;
        }
        return (int)x0;
    }
};

        分析:时间复杂度:O(logx),空间复杂度:O(1)。

        3、袖珍计算器算法:

袖珍计算器算法是利用指数函数exp和对数函数ln来代替平方根的方法。即

        代码如下:

class Solution {
public:
    int mySqrt(int x) {
        if(x==0) return 0;
        int ans=exp(0.5*log(x));
        return ((long long)(ans+1)*(ans+1))<=x?ans+1:ans;//判断误差
    }
};

        分析:时间复杂度:O(1),空间复杂度:O(1)。由于指数函数和对数函数返回的是浮点数值,故还需要误差判断。

        总结:二分排序需要注意循环条件和后续的区间赋值问题。

        第三篇博客,完成!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值