大家好,我是涛哥。
今天,我们来看华为的一道面试题目:如何判断一个整数是否为2的n次方,其中n为非数整数,要求效率尽可能高。
这是一道非常典型的面试题目,它有很多发散的形式,比如:如果把上述的2换成3、4、5,该怎么做才能高效呢?
接下来,我们从不同的角度分析,并给出上述所有情况的算法思路和代码验证,希望大家有所收获,顺便通过面试。
涛哥在华为松山湖闲逛所拍
判断2的n次方
2的n次方的判断,是一个比较常见的问题。容易看出,2的n次方的二进制中,有且仅有一个1, 所以,可用如下思路来判断:
package main
import "fmt"
func is2Pow(n uint32) bool {
if n == 0 {
return false
}
if n & (n - 1) == 0 {
return true
}
return false
}
func main() {
for i := uint32(0); i < 100; i++ {
if is2Pow(i) {
fmt.Println(i)
}
}
}
判断3的n次方
因为3是质数,所以可以先找出32位正整数中3的n次方的最大值(即3486784401),然后,思路就很自然了,如下:
package main
import "fmt"
func is3Pow(n uint32) bool {
if n == 0 {
return false
}
if 3486784401 % n == 0 {
return true
}
return false
}
func main() {
for i := uint32(0); i < 100; i++ {
if is3Pow(i) {
fmt.Println(i)
}
}
}
判断4的n次方
4的n次方,首先必须是2的n次方,且有4^n = (3+1)^n, 根据二项式定理可知:4^n % 3 = 1, 所以,算法代码如下:
package main
import "fmt"
func is4Pow(n uint32) bool {
if n == 0 {
return false
}
if n & (n - 1) != 0 {
return false
}
if n % 3 == 1 {
return true
}
return false
}
func main() {
for i := uint32(0); i < 100; i++ {
if is4Pow(i) {
fmt.Println(i)
}
}
}
判断5的n次方
既然前面的方法都用了,那现在可考虑使用通用的方法了,如下:
package main
import "fmt"
func is5Pow(n uint32) bool {
if n == 0 {
return false
}
if n == 1 {
return true
}
for {
if n % 5 != 0 {
return false
}
n = n / 5
if n < 5 {
break
}
}
if n == 1 {
return true
}
return false
}
func main() {
for i := uint32(0); i < 100; i++ {
if is5Pow(i) {
fmt.Println(i)
}
}
}
整体来看,上述四种方法各有技巧,希望大家从中举一反三,揣摩到算法优化的思路,横扫类似的笔试面试问题,拿到满意的offer,也欢迎大家在评论区讨论交流。