367. 有效的完全平方数

175 阅读1分钟

「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战

题目

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

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

实例1

输入: num = 16
输出: true

实例2

输入: num = 14
输出: false

思路分析

直接使用库函数自然是简单,不过也失去了做这道题的意义,做这道题不急,我们可以一点点优化。首先就是犯下了首先之罪的枚举。

bool isPerfectSquare(int num) {
        for(int i = 1; i <= num; i ++){
            if(i * i == num){
                return true;
            }
        }
        return false;
    }

image.png

很遗憾,由于int溢出而出现了错误。

bool isPerfectSquare(int num) {
        for(long i = 1; i <= num; i ++){
            if(i * i == num){
                return true;
            }
        }
        return false;
    }

然而这样会造成超时,所以O(N)并不好用,那么除了由于乘数为2时,另一个乘数一定小于等于n/2,那么我们就可以利用这一条将他变为

bool isPerfectSquare(int num) {
        for(long i = 2; i <= num/2; i ++){
            if(i * i == num){
                return true;
            }
        }
        return num == 1;
    }

但是这样其实还是浪费时间,进一步利用这个性质去通过让双指针不断逼近的方式来找到最优解

 bool isPerfectSquare(int num) {
        int p = 1, q = num;
        while(p < q){
            p++;
            q = num / p;
        }
        return p == q && p * q == num;
    }

这样只需要不断判断是否p<q的方式让两个指针不断逼近,当不满足这个条件时比较pq是否相等以及p * q是否等于num

这种方法的时间复杂度是根号n,我们还可以用二分解决这个问题。

bool isPerfectSquare(int num) {
        int p = 0, q = num;
        while(p < q){
           long mid = (p + q) / 2;
           cout << mid;
            if (mid * mid == num)return true;
            else if (mid * mid > num){
                q = mid - 1;
            }else  {
                p = mid + 1;
            }
        }
        return p == q && p * q == num;
    }

许久不用二分,甚至有些生疏,在三个if里面写了个死循环。。。