每周完成一个 ARTS:
Algorithm: 每周至少做一个 LeetCode 的算法题
Review: 阅读并点评至少一篇英文技术文章
Tips: 学习至少一个技术技巧
Share: 分享一篇有观点和思考的技术文章
367. Valid Perfect Square
题目:367. 有效的完全平方数
难度:Easy
题意:给定一个正整数 num,编写一个函数,如果 num 是一个完全平方数,则返回 True,否则返回 False。
说明:不要使用任何内置的库函数,如 sqrt
。
示例一:
Input: 16
Output: true
示例二:
Input: 14
Output: false
解法:
本题相对比较容易,目前来看有四种解法:暴力搜索、公式法、二分搜索和牛顿法。下面分别就这四种解法作出解释和代码。
暴力搜索法
从 1 开始遍历,直到 num,判断 i 的平方是否为 num,如果是,返回 True,否则返回 False。
代码:
class Solution:
def isPerfectSquare(self, num: int) -> bool:
for i in range(1, num+1):
if i*i == num:
return True
return False
这个解法,思路上是没错的,但是当我们提交代码的时候就会发现,OJ 报错“Time Limit Exceeded”,说明我们的算法耗时太长。
时间复杂度 O(n),空间复杂度 O(1)。
公式法
我们根据数学知识知道,一个首项为 1、等差为 2 的等差数列的前 n 项和,即为 n 的平方:
\[1 + 3 + 5 + \cdots + (2n - 1) = \frac{[1+ (2n - 1)]\times n}{2} = n^2\]我们可以利用这个方法来解这道题:让 num 逐项减去上述等差数列的前 n 项,一直减到 num 大于 0,判断结果,如果为 0,那么证明 num 是完全平方数,否则不是。
代码:
class Solution:
def isPerfectSquare(self, num: int) -> bool:
i = 1
while num > 0:
num -= i
i += 2
if num == 0:
return True
else:
return False
时间复杂度 O(n),空间复杂度 O(1)。
二分搜索
借鉴了二分查找的思路,设置 left、right、mid 指针,当 left <= right 的时候,计算 mid,如果 mid == num/mid,那么返回 True,否则重新计算 mid,在计算完毕之后,如果还没有找到 mid == num/mid,那么返回 False。
代码:
class Solution:
def isPerfectSquare(self, num: int) -> bool:
left, right = 1, num
while left <= right:
mid = left + (right - left) // 2
if mid > num/mid:
right = mid - 1
elif mid < num/mid:
left = mid + 1
else:
return True
return False
由于是二分查找,时间复杂度为 O(log n),空间复杂度为 O(1)。
牛顿法
首先我们需要对牛顿法的数学原理做一些了解。
如图所示,有曲线 $f(x)$,在 $f(x_n)$ 处画一条切线,与 x 轴相交于 $x_{n+1}$,继续在 $f(X_{n+1})$ 处画一条切线,与 x 轴相交于 $x_{n+2}$。如果继续这个步骤 m 次,我们会发现,第 m 个交点 $x_{n+m}$ 会无限逼近方程 $f(x) = 0$ 的根 $x_0$,最终能够得到一个与精确值无限接近的近似值。
此处我们的问题讨论的是平方(根),那么我们如果能找到 num 的整数平方根,就说明 num 为完全平方根数。
此处求 num 的平方根即是求曲线方程为 $f(x) = x^2 - N$ 的零点。函数 $f(X)$ 的导数为 $f’(x) = 2x$,那么曲线在 $(x_n, x^2n - N)$ 处的切线的斜率为 $2x_n$,切线方程为 $y - (x^2_n - N) = 2x_n * (x - x_n)$,即 $y = 2x_n x - x^2_n - N$,切线与 x 轴的交点为 $x{n+1} = \frac{1}{2}(x_n + \frac{N}{x_n})$。
我们可以一直将 $x_{n+1}$ 的平方与 num 相比,如果 $x^2{n+1}$ 大于 num,那么就再次循环,直到 $x^2{n+1}$ 不大于 num,如果此时两者相等,那么即可判断 num 为完全平方数,否则不为完全平方数。
代码:
class Solution:
def isPerfectSquare(self, num: int) -> bool:
r = num
while r*r > num:
r = (r + num / r) // 2
if r*r == num:
return True
else:
return False
时间复杂度 O(log n),空间复杂度 O(1)。
Generative Adversarial Networks - The Story So Far
本周阅读了 FloydHub 上的一篇介绍 GAN(生成对抗网络)的发展历史的文章,Generative Adversarial Networks - The Story So Far。这篇文章从 GAN 的历史角度,对 10 种 GAN 以及他们的变体进行了较为详细的介绍,并附上了代码和 Paper,如果你想入门 GAN,这是非常值得一读的好文章。
推荐两个有趣好用的 vim 插件
Vim 中的增删改查
增:
删:
改:
查:
:noh
取消高亮