问题链接
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和博客园所有,欢迎转载和商用,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.