[LeetCode] Valid Perfect Square 检验完全平方数

 

Given a positive integer num, write a function which returns True if num is a perfect square else False.

Note: Do not use any built-in library function such as sqrt.

Example 1:

Input: 16
Returns: True

Example 2:

Input: 14
Returns: False

Credits:
Special thanks to @elmirap for adding this problem and creating all test cases.

 

这道题给了我们一个数,让我们判断其是否为完全平方数,那么显而易见的是,肯定不能使用brute force,这样太不高效了,那么最小是能以指数的速度来缩小范围,那么我最先想出的方法是这样的,比如一个数字49,我们先对其除以2,得到24,发现24的平方大于49,那么再对24除以2,得到12,发现12的平方还是大于49,再对12除以2,得到6,发现6的平方小于49,于是遍历6到12中的所有数,看有没有平方等于49的,有就返回true,没有就返回false,参见代码如下:

 

解法一:

class Solution {
public:
    bool isPerfectSquare(int num) {
        if (num == 1) return true;
        long x = num / 2, t = x * x;
        while (t > num) {
            x /= 2;
            t = x * x;
        }
        for (int i = x; i <= 2 * x; ++i) {
            if (i * i == num) return true;
        }
        return false;
    }
}; 

 

下面这种方法也比较高效,从1搜索到sqrt(num),看有没有平方正好等于num的数:

 

解法二:

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

 

我们也可以使用二分查找法来做,要查找的数为mid*mid,参见代码如下:

 

解法三:

class Solution {
public:
    bool isPerfectSquare(int num) {
        long left = 0, right = num;
        while (left <= right) {
            long mid = left + (right - left) / 2, t = mid * mid;
            if (t == num) return true;
            else if (t < num) left = mid + 1;
            else right = mid - 1;
        }
        return false;
    }
};

 

下面这种方法就是纯数学解法了,利用到了这样一条性质,完全平方数是一系列奇数之和,例如:

1 = 1
4 = 1 + 3
9 = 1 + 3 + 5
16 = 1 + 3 + 5 + 7
25 = 1 + 3 + 5 + 7 + 9
36 = 1 + 3 + 5 + 7 + 9 + 11
….
1+3+…+(2n-1) = (2n-1 + 1)n/2 = n*n

这里就不做证明了,我也不会证明,知道了这条性质,就可以利用其来解题了,时间复杂度为O(sqrt(n))。

 

解法四:

class Solution {
public:
    bool isPerfectSquare(int num) {
        int i = 1;
        while (num > 0) {
            num -= i;
            i += 2;
        }
        return num == 0;
    }
};

 

下面这种方法是第一种方法的类似方法,更加精简了,时间复杂度为O(lgn):

 

解法五:

class Solution {
public:
    bool isPerfectSquare(int num) {
        long x = num;
        while (x * x > num) {
            x = (x + num / x) / 2;
        }
        return x * x == num;
    }
};

 

这道题其实还有O(1)的解法,这你敢信?简直太丧心病狂了,详情请参见论坛上的这个帖子

 

类似题目:

Sqrt(x)

 

参考资料:

https://leetcode.com/discuss/110639/o-logn-bisection-method

https://leetcode.com/discuss/110792/simple-for-loop-o-sqrt-n

https://leetcode.com/discuss/110638/a-square-number-is-1-3-5-7-java-code

https://leetcode.com/discuss/110659/o-1-time-c-solution-inspired-by-q_rsqrt

https://leetcode.com/discuss/110671/3-4-short-lines-integer-newton-most-languages

 

    原文作者:Grandyang
    原文地址: http://www.cnblogs.com/grandyang/p/5619296.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞