• 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;
        }
    
  • 相关阅读:
    request请求与响用
    flask源码分析
    falsk使用
    偏导函数
    flaskwsgiref
    请求和响应的周期执行顺序与异常和过滤器和模板语法
    C#读取EXCEL数据
    ecshop
    Log4Net记录日志(mvc)
    select和checkbox回绑
  • 原文地址:https://www.cnblogs.com/xym4869/p/12826631.html
Copyright © 2020-2023  润新知