LeetCode 有效数的完全平方数/x 的平方根[二分法]

1,159 阅读2分钟

这是我参与更文挑战的第 12 天,活动详情查看: 更文挑战

有效数的完全平方数(367)

题目描述

给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false

进阶:不要 使用任何内置的库函数,如 sqrt

示例 1:

输入:num = 16
输出:true

示例 1:

输入:num = 14
输出:false

提示

  • 1 <= num <= 2^31 - 1

思路分析

求平方数的完全平方数,或者求某个数的平方根,很多时候都可以用二分法,默认数是从小到大,这样通过二分查找,查找的次数是很少的。

求题解还有一个需要注意的,就是可能遇到 int 数越界的问题,如果我们用 mid * mid 来判断是否等于目标值时,可能造成 mid * mid 越界,当然也可以用 long 进行处理,不过我们可以用 num/mid == mid && num % mid == 0 这个条件进行判断。

二分查找有一定的套路,首先定义 low 和 high,while 循环的判断条件一直是 low <= high,对于 low == high,必要的时候特殊处理,在 while 内部补充,返回值永远是 mid;low、high 的更新永远是 low = mid + 1 和 high = mid - 1;

对于非确定性的查找,使用前后探测法,来确定搜索区间。先处理命中情况,再处理左右半部分查找的情况。

代码展示

解法一:时间复杂度是O(logn){O(logn)},空间复杂度是O(1){O(1)}

public boolean isPerfectSquare(int num) { //如果需要k个小数,怎么解答???
        if (num == 0 || num == 1){
            return true;
        }
        int low = 0;
        int high = (num + 1)/2; //5
        while (low <= high){
            int mid = low + (high - low)/2;
            if (mid == 0){
                return false;
            }

            if (num/mid == mid && num % mid == 0){ //num % mid == 0 很重要
                return true;
            } else if (num/mid > mid){ // 18       9
                low = mid + 1;
            } else {
                high = mid - 1;
            }
        }
        return false;
    }

x 的平方根(69)

题目描述

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

示例 1:

输入: 4
输出: 2

示例 2:

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

思路分析

这道题也是用二分法查找,解题思路和上面一样,这道题还需要截取小数部分,只取整数,需要注意个细节x / mid >= mid,这里需要等号。

代码展示

解法一:时间复杂度是O(logn){O(logn)},空间复杂度是O(1){O(1)}

public int mySqrt(int x) {  //5  2
        if (x <= 1){
            return x;
        }
        int low = 0;
        int high = x/2+1; //3
        while (low <= high){
            int mid = low + (high - low)/2;
            if (x / mid == mid && x % mid == 0){
                return mid;
            } else if (x / mid >= mid){ //这里很重要,还要加上等号   比如5/2 = 2
                low = mid + 1;
                if (x / low < low){
                    return mid;
                }
            } else {
                high = mid - 1;
            }
            if (low == high){
                if (low * high == x){
                    return low;
                }
            }
        }
        return -1;

    }

总结

平方根和完全平方数都可以使用二分法解答,我们需要好好掌握二分法解法。二分查找有一定的套路,首先定义 low 和 high,while 循环的判断条件一直是 low <= high,对于 low == high,必要的时候特殊处理,在 while 内部补充,返回值永远是 mid;low、high 的更新永远是 low = mid + 1 和 high = mid - 1;

对于非确定性的查找,使用前后探测法,来确定搜索区间。先处理命中情况,再处理左右半部分查找的情况。