LeetCode 367. Valid Perfect Square

问题链接

LeetCode 367. Valid Perfect Square

题目解析

判断一个正数是否是完全平方数,不可使用sqrt函数。

解题思路

这是一道简单题,但是却挺有思考价值的。本题有很多种解法,思路各异,可以都看看。

无数种解法

解法一

数学里有一个概念叫做等差数列,完全平方数恰好是奇数等差数列之和。1+3+5+...+(2n-1)=(1+2n-1)n/2=n^2。既然有了这个,那就好办了,从小到大依次减去奇数,最后判断是否等于0即可。时间复杂度为 \(O(sqrt(n))\)。参考代码如下:

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

解法二

从1搜索到sqrt(num),时间复杂度为 \(O(sqrt(n))\)。参考代码如下:

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

解法三

其实就是搜索一个数,自然可以想到二分法。时间复杂度 \(O(lg(n))\)。参考代码如下:

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;
    }
};

解法四

万恶的算法,竟然还有一个 \(O(1)\) 的解法,不过很难弄懂。参考链接:O(1) time c++ solution inspired by Q_rsqrt。想弄懂的还可以参考一下这个概念: Fast Inverse Square Root

代码大概是这个样子的,学不来学不来:

class Solution {
public:
    bool isPerfectSquare(int num) {
        if (num < 0) return false;
        int root = floorSqrt(num);
        return root * root == num;
    }

    int32_t floorSqrt(int32_t x) {
        double y=x; int64_t i=0x5fe6eb50c7b537a9;
        y = *(double*)&(i = i-(*(int64_t*)&y)/2);
        y = y * (3 - x * y * y) * 0.5;
        y = y * (3 - x * y * y) * 0.5;
        i = x * y + 1; return i - (i * i > x);
    }
};

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

本文版权归作者AlvinZH和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.


posted @ 2018-05-17 23:17  AlvinZH  阅读(563)  评论(0编辑  收藏  举报