4. 69 x的平方根(easy)

一、题目

Given a non-negative integer x, compute and return the square root of x.

Since the return type is an integer, the decimal digits are truncated, and only the integer part of the result is returned.

Note: You are not allowed to use any built-in exponent function or operator, such as pow(x, 0.5) or x ** 0.5.

 

Example 1:

Input: x = 4
Output: 2
Example 2:

Input: x = 8
Output: 2
Explanation: The square root of 8 is 2.82842..., and since the decimal part is truncated, 2 is returned.
 

Constraints:

0 <= x <= 231 - 1

二、 思路

其实还是满足二分法的使用条件,数组元素无重复+从小到大排列,只不过数组就是[0,x],判断条件也稍微改变了一下而已。

二、自己写的

1.代码

第一次写

class Solution {
    public int mySqrt(int x) {

        //必须得用左闭右开的,想想x=1的情况
        int left = 0, right = x, mid = 0;

        if (x == 1)
            return 1;
        
        if (x == 0)
            return 0;

        while (left < right) {
            mid = left + (right - left) / 2;
            int r = mid * mid;
            // r>x 最终结果一定在当前mid的左边,往左走
            if (r > x)
                right = mid;
            // r<x 不一定,因为example2就说明了小也可能是答案
            else if (r < x) {
                //如果mid+1的平方大于x了,那当前mid就是output
                if ( (mid + 1) * (mid + 1) > x)
                    return mid;
                //否则最终结果一定在当前mid的右边,往右走
                else
                    left = mid + 1;
            }
            else
                return mid;
        }
        return -1;
    }
}

//错误1:提交了两次,WA在两个特殊的例子0和1上,所以0,1做了特殊处理,所以没必要非得左闭右开了
//错误2:这样求r可能数值太大了,溢出了,所以要判断x开平方以后的值和mid比

第二次写

class Solution {
    public int mySqrt(int x) {

        int left = 0, right = x, mid = 0;

        if (x == 1)
            return 1;
        
        if (x == 0)
            return 0;

        while (left < right) {
            mid = left + (right - left) / 2;
            //把r = mid 
            // r>x 最终结果一定在当前mid的左边,往左走
            if ((x / mid) < mid)
                right = mid;
            // r<x 不一定,因为example2就说明了小也可能是答案
            else if (mid < (x / mid)) {
                //如果mid+1的平方大于x了,那当前mid就是output
                if ( (mid + 1) > (x / (mid + 1)))
                    return mid;
                //否则最终结果一定在当前mid的右边,往右走
                else
                    left = mid;
            }
            else
                return mid;
        }
        return -1;
    }
}

//正确,感觉有的时候不必纠结+1 -1的范围,实在不行就不+1 -1了,只不过多查俩数,和复杂度没太大关系,还能少动脑子。

第三次写

class Solution {
    public int mySqrt(int x) {
        
        //数组的话左闭右闭定义left=0,right=nums.length-1
        //这现在是个数,把他当做一个数组的话,left=0,right=x 比如x=3,left=0相当于[0,1,2,3],left=0,right=nums.length-1(3)
        int left = 0, right = x, mid = 0;
        
        //特殊情况x=0的时候,直接返回0
        if (x == 0)
            return 0;
        //特殊情况x=1的时候,直接返回1
        if (x == 1)
            return 1;

        while (left <= right) {
            mid = left + (right - left) / 2;
            //要注意防止溢出,mid可能取到很大,用mid*mid和x判断,可能mid*mid大的离谱 
            if (mid > (x / mid))
                right = mid- 1;
            else if (mid < (x / mid)){
                if ((mid + 1) > (x / (mid + 1)))
                    return mid;
                else if ((mid + 1) == (x / (mid + 1)))
                    return mid + 1;
                else
                    left = mid + 1;
            }
            else
                return mid;
        }

        return -1;
    }
}

//正确,其实还是要纠结+1 -1的范围,有些题就因为这个会TLE,怎么把数转换成数组上的左闭右开左闭右闭见第三次的注释

三、标准答案

1.方法一(二分法求)

public class Solution {

    public int mySqrt(int x) {
        // 特殊值判断
        if (x == 0) {
            return 0;
        }
        if (x == 1) {
            return 1;
        }

        int left = 1;
        int right = x / 2;
        // 在区间 [left..right] 查找目标元素
        while (left < right) {
            int mid = left + (right - left + 1) / 2;
            // 注意:这里为了避免乘法溢出,改用除法
            if (mid > x / mid) {
                // 下一轮搜索区间是 [left..mid - 1]
                right = mid - 1;
            } else {
                // 下一轮搜索区间是 [mid..right]
                left = mid;
            }
        }
        return left;
    }
}

2.方法二(牛顿迭代法)

class Solution {
    int s;
    
 public int mySqrt(int x) {
     s=x;
     if(x==0) return 0;
    return ((int)(sqrts(x)));
  }
    
    public double sqrts(double x){
      double res = (x + s / x) / 2;
    if (res == x) {
      return x;
    } else {
      return sqrts(res);
    }
    } 
}

3.总结

无。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值