zoukankan      html  css  js  c++  java
  • [LeetCode] 367. 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;
                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) 的解法,这你敢信?简直太丧心病狂了,详情请参见论坛上的这个帖子

    Github 同步地址:

    https://github.com/grandyang/leetcode/issues/367

    类似题目:

    Sqrt(x)

    参考资料:

    https://leetcode.com/problems/valid-perfect-square/

    https://leetcode.com/problems/valid-perfect-square/discuss/83872/O(1)-time-c%2B%2B-solution-inspired-by-Q_rsqrt

    https://leetcode.com/problems/valid-perfect-square/discuss/83874/A-square-number-is-1%2B3%2B5%2B7%2B...-JAVA-code

    https://leetcode.com/problems/valid-perfect-square/discuss/83902/Java-Three-Solutions-135..-SequenceBinary-SearchNewton

    LeetCode All in One 题目讲解汇总(持续更新中...)

  • 相关阅读:
    咨询
    xcode技巧
    礼仪
    asi 网络框架
    iOS 开发问题 书籍 价值 改名 创业大赛app
    PS,UI,美工
    运营推广
    多线程 并发 文章
    手机技巧 文章
    javaScript 类文章
  • 原文地址:https://www.cnblogs.com/grandyang/p/5619296.html
Copyright © 2011-2022 走看看