今天看到小伙在看一个判断一个数是否为2的N次方的博客,我有点印象,就过去装逼了结果一下子还真没想出来,装逼失败!
这道题目其实是 leetcode 上面的第231道题目,题目内容如下:
给定一个整数,编写一个函数来判断它是否是 2 的幂次方 • 1
我一开始是想到如果是10进制内10的多少次方的时候应该是什么样子:
10^n | 数值 | n |
10^0 | 1 | 0 |
10^1 | 10 | 1 |
10^2 | 100 | 2 |
10^3 | 1000 | 3 |
我们很自然的看出来,如果我们平时的10进制,其实就是一位数上是1,其他都是0。这个想到我们计算2^n的时候,应该是1,2,4,8,16依次下去,由此想到这种情况下在二进制的情况:
2^n | 数值 | 10进制 |
2^0 | 1 | 1 |
2^1 | 10 | 2 |
2^2 | 100 | 4 |
2^3 | 1000 | 8 |
我们其实很容易发现,2的多少次方的情况就是二进制位数上一个数是1其他都是0,我们的思路其实就是想办法把二进制数中的1消掉,剩下的是0就行,当然前提条件是这个数>大于0,我们可以使用二进制的中的清零最低位的1操作x&(x-1),这个表示的是我们把最低位的1去掉,看看剩下的值,运算过程如下:
2^n | n | n-1 | n&n-1 |
2^0 | 1 | 0 | 0 |
2^1 | 10 | 01 | 00 |
2^2 | 100 | 011 | 000 |
2^3 | 1000 | 0111 | 0000 |
其他情况也可以看看
十进制 | n | n-1 | n&n-1 |
3 | 11 | 10 | 10 |
5 | 101 | 100 | 100 |
6 | 110 | 101 | 100 |
7 | 111 | 110 | 110 |
可以看到n&(n-1)的效果就是会把n的二进制位最低的那位1抹掉,在2^n次方的情况抹掉一个0剩下的就全是0了,其他情况的话不会是0,所以相应的只要位运算的操作就可以出来结果,代码贴上,附上测试数据:
public class Leecode_231_35 { public static void main(String[] args) { Leecode_231_35 lc = new Leecode_231_35(); System.out.println(lc.isPowerOfTwo(0)); System.out.println(lc.isPowerOfTwo(1)); System.out.println(lc.isPowerOfTwo(2)); System.out.println(lc.isPowerOfTwo(3)); System.out.println(lc.isPowerOfTwo(4)); System.out.println(lc.isPowerOfTwo(5)); System.out.println(lc.isPowerOfTwo(6)); System.out.println(lc.isPowerOfTwo(7)); System.out.println(lc.isPowerOfTwo(8)); System.out.println(lc.isPowerOfTwo(9)); System.out.println(lc.isPowerOfTwo(-2147483648)); } public boolean isPowerOfTwo(int n) { return n > 0 && (n &= n - 1) == 0; } }
当然,这种高效一次运算的操作,自然时间复杂度就是最最让人喜欢的O(1)了