题目描述
思路解析动画文字版
记住这句话:2 的幂在二进制里「只有一个 1」。把每一位扫一遍数 1 的个数,恰好一个就是答案。
先把 16 写成二进制 00010000(左边是高位)。我们要从左到右扫每一位,数里面总共有几个 1。
指针走到第 0 位,这一位是 0。是 0,不是 1,直接跳过。
这一位是 0,1 的个数不变,仍然是 0。继续看下一位。
指针走到第 1 位,这一位是 0。是 0,不是 1,直接跳过。
这一位是 0,1 的个数不变,仍然是 0。继续看下一位。
指针走到第 2 位,这一位是 0。是 0,不是 1,直接跳过。
这一位是 0,1 的个数不变,仍然是 0。继续看下一位。
指针走到第 3 位,这一位是 1。是 1,把 1 的个数加一。
这一位是 1,1 的总个数变成 1(绿色高亮的就是目前数到的所有 1)。
指针走到第 4 位,这一位是 0。是 0,不是 1,直接跳过。
这一位是 0,1 的个数不变,仍然是 1。继续看下一位。
指针走到第 5 位,这一位是 0。是 0,不是 1,直接跳过。
这一位是 0,1 的个数不变,仍然是 1。继续看下一位。
指针走到第 6 位,这一位是 0。是 0,不是 1,直接跳过。
这一位是 0,1 的个数不变,仍然是 1。继续看下一位。
指针走到第 7 位,这一位是 0。是 0,不是 1,直接跳过。
这一位是 0,1 的个数不变,仍然是 1。继续看下一位。
扫完所有位,二进制 00010000 里只有 1 个 1(绿色那位)。恰好一个 1,所以 16 是 2 的幂,返回 true。
换个反例:把 12 写成二进制 00001100。还是从左到右逐位数 1,看它能不能满足「恰好一个 1」。
指针走到第 0 位,这一位是 0。是 0,跳过。
这一位是 0,1 的个数不变,仍然是 0。
指针走到第 1 位,这一位是 0。是 0,跳过。
这一位是 0,1 的个数不变,仍然是 0。
指针走到第 2 位,这一位是 0。是 0,跳过。
这一位是 0,1 的个数不变,仍然是 0。
指针走到第 3 位,这一位是 0。是 0,跳过。
这一位是 0,1 的个数不变,仍然是 0。
指针走到第 4 位,这一位是 1。是 1,把 1 的个数加一。
这一位是 1,1 的总个数变成 1。
指针走到第 5 位,这一位是 1。是 1,把 1 的个数加一。
这一位是 1,1 的总个数变成 2(已经超过一个了)。
指针走到第 6 位,这一位是 0。是 0,跳过。
这一位是 0,1 的个数不变,仍然是 2。
指针走到第 7 位,这一位是 0。是 0,跳过。
这一位是 0,1 的个数不变,仍然是 2。
扫完反例:12 的二进制里有 2 个 1(标红那两位),多于一个。所以 12 不是 2 的幂,返回 false。
三个高频追问:一个 1 为何等价 2 的幂、n&(n-1) 的原理、以及负数/0 边界。
参考代码
def isPowerOfTwo(n): if n <= 0: # 2 的幂一定是正数 return False # 数二进制里 1 的个数,恰好一个才是 2 的幂 return bin(n).count('1') == 1# 位运算一行版(更快):# return n > 0 and n & (n - 1) == 0复杂度
- 时间:O(1),int 最多 32 位,数 1 的个数最多看 32 位,与 n 大小无关,是常数级
- 空间:O(1),只用一个计数器,不开额外数组
易错点
面试追问把动画讲成自己的话
追问为什么「二进制只有一个 1」就等价于「是 2 的幂」?
追问n & (n-1) == 0 为什么能判断 2 的幂?
追问如果允许负数输入怎么办?
这道题到这就讲完了。动画和文字是同一套思路——别光看,关掉页面自己默写一遍。然后顺着主线继续:
汉明距离
LeetCode 461 · 简单 · 沿着 位运算套路 继续往下推进
把这道题真正学会,再走
图解算法年卡 ¥99 /年
- ✓本题每步动画的吴师兄语音讲解(全站陆续覆盖)
- ✓小欧带 8 步通关训练——追问到不看答案也能写对、能 30 秒讲给面试官听
- ✓学习报告,记录每道题的掌握程度
76k+ GitHub Star · 吴师兄开源图解算法,几十万开发者在看的算法讲解
想成体系刷透这类套路?去图解算法专题