69.x的平方根(简单)

LeetCode 69.x的平方根题目链接:

题目描述:

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

示例 1:

输入: 4
输出: 2

示例 2:

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

题目分析:

一眼看到这道题,第一种方法,我们肯定会想到直接调用数学函数求解,笔试面试这样写想必你已经凉凉了。
第二种方法,我们也可以使用暴力破解法求解,首先,如果x为0或1,则它们的非负平方根是它们本身。我们可以大致取中点值,从1到中点值进行遍历,如果当前数平方小于等于x且下一位数平方大于x,则当前数为平方根,但暴力解法耗时长。
第三种方法,二分查找,首先定义左右边界,左边界为0,右边界为x,当左边界小于等于右边界执行循环,求出这段区间的中点值,用中点值的平方与x进行比较,如果中点值平方大于x,则说明答案应该在左子区间,我们对区间范围进行缩小,更新右边界为中点值左边元素。如果中点值平方小于x,则说明答案应该在右子区间,我们对区间范围进行缩小,更新左边界为中点右边元素。如果中点值平方刚好等于x,在说明中点值就是我们要求的答案。如果在循环遍历过程中,左边界大于右边界且左边界平方大于x而右边界平方小于x,即右边界值比左边界值小,返回右边界值即可。
第四种方法,牛顿迭代法,我们可以把这道题转化为函数求解问题。依题意,我们可以将求解平方根转换为求解函数 f ( y ) = y 2 − x = 0 f(y) = y^{2} - x = 0 f(y)=y2−x=0的解。根据牛顿迭代法公式 x n + 1 = x n − f ( x n ) f ′ ( x n ) x_{n+1} = x_{n} − \frac{f(x_{n})}{f′(x_{n})} xn+1​=xn​−f′(xn​)f(xn​)​。因为 f ( y ) = y 2 − x = 0 f(y) = y^{2} − x = 0 f(y)=y2−x=0,我们把函数代入迭代公式得到 y n + 1 = y n + x y n 2 y_{n+1} = \frac{y_{n} + \frac{x}{y_{n}}}{2} yn+1​=2yn​+yn​x​​,再按牛顿迭代法求解即可。

题解一(笔试面试必挂解):

执行用时: 1 ms
内存消耗: 35.2 MB

class Solution {
    public int mySqrt(int x) {
        // 笔试面试必挂解法,直接调用库函数
        return (int) Math.sqrt(x);
    }
}

题解二(暴力解法):

执行用时: 52 ms
内存消耗: 35.2 MB

class Solution {
    public int mySqrt(int x) {
        // 0的平方根为0,1的非负平方根为1
        if (x == 0 || x == 1)
            return x;
        // 取中点值
        long mid = x / 2;
        // 从1开始遍历
        for (long i = 1; i <= mid; ++i) {
            // 如果当前数平方小于等于x且下一位数平方大于x
            if (i * i <= x && (i + 1) * (i + 1) > x)
                // 则当前数为平方根
                return (int)i;
        }
        // 方法一定要返回一个int值
        return -1;
    }
}

题解三(二分查找法):

执行用时: 2 ms
内存消耗: 35.5 MB

class Solution {
    public int mySqrt(int x) {
        // 定义左右边界
        long left = 0, right = x;
        // 当左边界小于等于右边界执行循环
        while(left <= right) {
            // 定义中点
            long mid = (left + right) / 2;
            // 中点值平方大于x,缩小范围至左区间
            if(mid * mid > x)
                // 右边界更新为中点的左边元素
                right = mid - 1;
            // 中点值平方小于x,缩小范围至右区间
            else if(mid * mid < x)
                // 左边界更新为中点的右边元素
                left = mid + 1;
            // 中点值平方等于x,即mid为x的平方根
            else if(mid * mid == x)
                // 返回平方根整数部分
                return (int) mid;
        }
        // 如果左边界平方大于x而右边界平方小于x,即右边界值符合条件
        if(left * left > x && right * right < x)
            // 返回右边界值
            return (int) right;
        return -1;
    }
}

题解四(牛顿迭代法):

执行用时: 2 ms
内存消耗: 35.5 MB

class Solution {
    public int mySqrt(int x) {
        long a = x;
        while (a * a > x)
            a = (a + x / a) / 2;
        return (int) a;
    }
}

题目来源:力扣(LeetCode)

上一篇:BUUCTF - RE - [ACTF新生赛2020]Oruga


下一篇:Leetcode 69. x 的平方根 二分