题目
给定一个整数,编写一个函数来判断它是否是 2 的幂次方。
示例 1:
输入: 1
输出: true
解释: 2^0 = 1
示例 2:
输入: 16
输出: true
解释: 2^4 = 16
示例 3:
输入: 218
输出: false
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/power-of-two
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解题思路
直接法(更像是数学解题法)
从原理上直接判断 2 的幂次,幂指数逐次增大,每次都与给定的整数 n 做比较,有三种情况:
- 小于 n:幂指数继续递增
- 等于 n:返回 true
- 大于 n:返回 false
时间复杂度为O(log N)
位运算
2 的幂次最简单体现的只是计算结果,表面上看是数学幂次运算,从过程本质上分析,基于二进制,更偏向计算机运算思维,底层的实现过程。
2的幂次 | 二进制表示 |
---|---|
2^0 | 0000 0001 |
2^1 | 0000 0010 |
2^2 | 0000 0100 |
2^3 | 0000 1000 |
……
从表格中可以看出 2 的幂次二进制表示具有规律,即仅在某一位是 1 其余都是 0。于是,此题可以转化为判断给定的整数 n 的二进制表示的 1 的个数是否为一个。
- n & n - 1(去除二进制最右边的 1)
若为 2 的幂次,如 4 ,4(0100) & 3(0011) = 0 ;对于非 2 的幂次,如 9 , 9(1001) & 8(1000) = 8(1000),不为 0 ,可区分正确结果。 - n & -n(获得二进制最右边的 1)
若为 2 的幂次,如 2 ,2(0010) & -2(1110) = 2(0010) ;对于非 2 的幂次,如 9 , 9(1001) & -9(0111) = 1(0001),不为 9 ,可区分正确结果。
时间复杂度为O(1)
提交代码
直接法
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
i = 0
while i > -1:
if pow(2,i) < n:
i += 1
elif pow(2,i) == n:
return True
else:return False
位运算
- n & (-n)
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
if n == 0:
return False
return n & (-n) == n
可简化为↓
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
return n > 0 and n & (-n) == n
- n & (n - 1)
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
if n == 0:
return False
return n & (n - 1) == 0
可简化为↓
class Solution:
def isPowerOfTwo(self, n: int) -> bool:
return n > 0 and n & (n - 1) == 0
学习总结
- 偏向数学运算的题目按照计算机处理过程来分析,更有利于问题的高效解决,解题时从思路上只考虑数学表面解法欠缺学习意义;
- 二进制位运算的基础应用,获取二进制最右边的 1 和去除二进制最右边的 1,分别通过相反数(-n)和减一得到(n - 1)再与原数 & 运算。