题目描述
思路解析动画文字版
下面 16 步动画会按主解代码推进,而不是泛泛讲题型。
1. 看输入:输入 n = 16。第一步先看 n > 0 是否成立:16 大于 0,成立,可以继续判断。上面是 16 的二进制写法 10000。
2. 关键性质:核心性质:正的 2 的幂,二进制里恰好只有一个 1。16 = 10000,唯一的 1 在最高位(绿色标出),其余 4 位都是 0,符合这个性质。
3. 思路:用 n-1 验证:怎么用代码检验只有一个 1?技巧是计算 n & (n-1)。先准备好 n-1 = 15,下一步看 15 的二进制长什么样。
4. 算 n-1 的二进制(借位):n-1 = 15 的二进制是 01111。规律:减 1 会把 n 唯一的那个 1 变成 0,并把它右边原本的 0 全部翻成 1(紫色窗口,第 1~4 位)。最高位由 1 变 0。
5. 准备按位与:现在把 n = 10000 与 n-1 = 01111 逐位做与运算。与运算规则:两位都是 1 才得 1,否则得 0。从最高位(第 0 位,橙色)开始。
6. 第 0 位:第 0 位(橙色):n 是 1,n-1 是 0。1 AND 0 = 0。这一位结果为 0。
7. 第 1 位:第 1 位(橙色):n 是 0,n-1 是 1。0 AND 1 = 0。结果仍为 0。注意第 0 位已经定格为 0。
8. 第 2 位:第 2 位(橙色):n 是 0,n-1 是 1。0 AND 1 = 0。结果为 0。
9. 第 3、4 位:第 3、4 位(紫色窗口):n 都是 0,n-1 都是 1。0 AND 1 = 0。这两位结果也都是 0。
10. 合并结果:把五位拼起来:n & (n-1) = 00000,也就是十进制 0(整行绿色)。最高位的 1 被消掉,又没有别的 1 顶上来,所以全 0。
11. 判定为 true:两个条件:n > 0 成立,且 n & (n-1) == 0 成立。两者都满足,返回 true。16 确实是 2 的幂(16 = 2^4)。
12. 反例:n = 12:再看反例 n = 12 = 1100。它有两个 1(绿色标出),不止一个,所以不该是 2 的幂。看代码会不会判对。
13. 反例算 n-1:n-1 = 11 = 1011。减 1 只影响最低位的 1 及其右边:第 1 位的 1 变成 0,第 2、3 位翻成 1。但更高位的那个 1(第 0 位)没动。
14. 反例按位与:12 & 11 = 1100 & 1011 = 1000,第 0 位还留着一个 1(绿色),结果是 8,不为 0。因为 12 有两个 1,消掉最低位后还剩一个。
15. 反例判定为 false:n & (n-1) = 8,不等于 0,所以返回 false。12 不是 2 的幂,判断正确。这就是为什么 n & (n-1) == 0 能一行识别 2 的幂。
16. 别忘了 n > 0:边界:n = 0 时,0 & (0-1) 也等于 0,光看与运算会误判成 true。所以前面必须加 n > 0:0 不大于 0,返回 false。负数同理被挡住。
记住这题的代码骨架:题意约束先落到状态变量,再用循环或递归维护它。
参考代码
class Solution: def isPowerOfTwo(self, n): return n > 0 and (n & (n - 1)) == 0复杂度
- 时间复杂度:O(1),一次位运算
- 空间复杂度:O(1),无额外空间
易错点
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
汉明距离
LeetCode 461 · 简单 · 沿着 位运算套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题