题目描述
给定一个整数,写一个函数来判断它是否是 4 的幂次方。如果是,返回 true ;否则,返回 false 。
整数 n 是 4 的幂次方需满足:存在整数 x 使得n == 4^x
示例 1:
输入:n = 16
输出:true
示例 2:
输入:n = 5
输出:false
示例 3:
输入:n = 1
输出:true
提示:
-2^{31} <= n <= 2^{31} - 1
进阶:
你能不使用循环或者递归来完成本题吗?
题解
思路一
利用递归不停的除4,看最后商是否为1,代码如下
func isPowerOfFour(_ n: Int) -> Bool {
if n < 1 {
return false
}
if n == 1 {
return true
}
if n % 4 == 0 {
return isPowerOfFour(n / 4)
} else {
return false
}
}
思路二
4^x = 2^{2^x} = 2^{2x}
可证明一个数是若是4的x冥,那它一定是2的冥。
首先看2的冥二进制数的规律,2^0 = 1,即首位为1,其他位为0,而每右移一位,相等于乘于2,因此2^x即第x位为1,其他位皆为0,而2^x - 1则是第x位为0,其他位皆为1.
由此可得出。如果一个数n大于零,并且n & (n - 1) == 0,则n是2的冥。
接下来看4的冥二进制数的规律4^0 = 1,即首位为1,其他位为0,而每右移两位,相等于乘于4,因此4^x即第2x(偶数)位为1,其他位皆为0,我们可以构造一个奇数为都为1的mask0xaaaaaaaa与它相&。
由此可得出。如果一个数n大于零,并且n && (n - 1) == 0 && n & 0xaaaaaaaa == 0,则n是4的冥,代码如下
func isPowerOfFour(_ n: Int) -> Bool {
return n > 0 && n & (n - 1) == 0 && n & 0xaaaaaaaa == 0
}
思路三
有上面可知一个数是若是4的x冥,那它一定是2的冥。而把2的冥换成4的冥的话,可得如下2种情况。
2n={42n42n−1∗2n%2==0n%2==1
有上面的公式可得出,如果一个数,若是2的冥,他要么是4的冥,要么是4的冥的2倍。先暂时记住这个结论。
再继续之前,先介绍一下二项式定理。
(a+b)n=(0n)an∗b0+(1n)an−1∗b1+(2n)an−2∗b2+...+(n−1n)a1∗bn−1+(nn)a0∗bn
其中每个(kn) 为一个称作二项式系数的特定正整数,其等于k!(n−k)!n!。这个公式也称二项式公式或二项恒等式。因此4的冥展开如下:
4n=(3+1)n=(0n)3n∗10+(1n)3n−1∗11+(2n)3n−2∗12+...+(n−1n)31∗1n−1+(nn)30∗1n
4的冥对3求进行相除
4n/3=(3+1)n/3=((0n)3n∗10+(1n)3n−1∗11+(2n)3n−2∗12+...+(n−1n)31∗1n−1+(nn)30∗1n)/3=((0n)3n+(1n)3n−1+(2n)3n−2+...+(n−1n)31+(nn)30)/3=((0n)3n−1+(1n)3n−2+(2n)3n−3+...+(n−1n)30)⋯⋯1
有上可得出4的冥对3求余一定为1,同理也可得出4^n * 2对3求余一定为2.
由上面两个结论可以得出:
若一个数是2的冥,并且对3求余为1,那么则这个数为4的冥,代码如下
func isPowerOfFour(_ n: Int) -> Bool {
return n > 0 && n & (n - 1) == 0 && n % 3 == 1
}