LeetCode——x 的平方根/有效的完全平方数

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

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

A:
题目并不难,但不同的方法里面关于边界都有大大小小的坑。最好是自己写,才能知道坑在哪里……尤其注意最大值和0
1.二分法
算法:

如果 x < 2,返回 x。
令左边界为 2,右边界为 x / 2。
当 left <= right 时:
令 mid = (left + right) / 2,比较 mid * mid 与 x:
如果 mid * mid > x,更新右边界为 right = mid -1。
如果 mid * mid < x,更新左边界为 left = mid + 1。
如果 mid * mid == x,即整数平方根为 mid,返回 mid。
返回 right。

    public int mySqrt(int x) {
        if (x < 2)//特殊用例
            return x;
        long left = 2;//对待特殊用例,例如Integer.MAX_VALUE,使用long,解决求mid的问题
        long right = x / 2;
        while (left <= right) {
            long mid = (left + right) >>> 1;//无符号右移,相当于/2
            long square = mid * mid;
            if (square > x) {
                right = mid - 1;
            } else if (square < x) {
                left = mid + 1;
            } else {
                return (int) mid;
            }
        }
        return (int) right;
    }

Java 代码要注意到:如果中点 mid 声明为 int 类型,针对大整型测试用例通不过,因此变量需要声明为 long 类型

2.袖珍计算器
通常,袖珍计算器通过对数表或其他方式计算指数函数和自然对数。那么考虑将求平方根的运算转换为指数运算和对数运算:

\[\sqrt{x} = e^{\frac{1}{2}logx} \]

代码:

    public int mySqrt(int x) {
        if (x < 2)
            return x;
        int curr = (int) Math.exp(0.5 * Math.log(x)) + 1;//注意判断条件应该是取值+1的平方和x对比
        return (long) curr * curr > x ? curr - 1 : curr;//curr的平方为方便特殊取值应该用long
    }

3.递归+位运算
本方法的思路是使用递归,每一步都减小 x,直到 x < 2。

\[\sqrt{x} = 2*\sqrt{\frac{x}{4}} \]

递归式可写成:

\[mySqrt(x) = mySqrt(x>>2)<<1 \]

代码:

    public int mySqrt(int x) {
        if (x < 2)
            return x;
        int curr = (mySqrt(x >> 2) << 1) + 1;//因为符号先后的问题原因,记得加括号
        return (long) curr * curr > x ? curr - 1 : curr;
    }

4.牛顿法
牛顿法的思想:切线是曲线的线性逼近。

在迭代过程中,以直线代替曲线,用一阶泰勒展式(即在当前点的切线)代替原曲线,求直线与 x 轴的交点,重复这个过程直到收敛。

牛顿法的内容,建议看如何通俗易懂地讲解牛顿迭代法求开方?数值分析?
借鉴@liweiwei1419的推算:

代码:

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

类似解决:有效的完全平方数

Q:给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False。
说明:不要使用任何内置的库函数,如  sqrt。

示例 1:
输入:16
输出:True
示例 2:
输入:14
输出:False

A:
借鉴算平方根的代码。

1.二分法

    public boolean isPerfectSquare(int x) {
        if (x < 2)//特殊用例
            return true;
        long left = 2;//对待特殊用例,例如Integer.MAX_VALUE,使用long,解决求mid的问题
        long right = x / 2;
        while (left <= right) {
            long mid = (left + right) >>> 1;//无符号右移,相当于/2
            long square = mid * mid;
            if (square > x) {
                right = mid - 1;
            } else if (square < x) {
                left = mid + 1;
            } else {
                return true;
            }
        }
        return right * right == x;
    }

2.牛顿法

    public boolean isPerfectSquare(int num) {
        long x = num;
        while(x * x > num){
            x = (x + num / x) / 2;
        }
        return x * x == num;
    }
posted @ 2020-05-04 15:50  Shaw_喆宇  阅读(338)  评论(0编辑  收藏  举报