leetcode-剑指offer【15】-二进制中1的个数
[博客链接]
[题目描述]
[题目链接]
[github地址]
[思路介绍]
思路一:暴力法+位运算
- 通过判断 n & 1 == 1 判断末位是否为1
- 然后无符号右移即可
- 这个的测试用例真的挺奇怪的居然偶尔会TLE
public int hammingWeight(int n) {int res = 0;while (n != 0) {if ((n & 1) == 1) {res += 1;}n >>>= 1;}return res;}
时间复杂度O(k)k最大32
思路二:java.Integer库的调用
public int hammingWeight(int n) {return Integer.bitCount(n);}
时间复杂度O(logk)k最大32
思路三:位运算的奇思妙想
- n &= (n-1) 会将最后位1变成0
- n-1表示把最后一位的1右边全变成1,当前位变为1,然后与n与运算则表示当前位右侧以及当前位都变成0
- 计算次数则为1的个数

public int hammingWeight(int n) {int res = 0;while (n != 0) {n &= n - 1;res += 1;}return res;}
时间复杂度O(k)-主要优化的是删除了中间为0的运算
思路四:思路一的多种写法
- 虽然我也没看出来啥优化
public int hammingWeight(int n) {int ret = 0;for (int i = 0; i < 32; i++) {if ((n & (1 << i)) != 0) {ret += 1;}}return ret;}
时间复杂度O(k),可能是leetcode更信任常量?
思路五:思路一的多种写法
public int hammingWeight(int n) {int res = 0;while (n != 0) {res += (n & 1);n >>>= 1;}return res;}
时间复杂度O(k)
思路六-logk写法
- 这个是java库的写法
- 手写了一次运算过程

简化后运算过程

public int hammingWeight(int i) {// HD, Figure 5-2i = i - ((i >>> 1) & 0x55555555);i = (i & 0x33333333) + ((i >>> 2) & 0x33333333);i = (i + (i >>> 4)) & 0x0f0f0f0f;i = i + (i >>> 8);i = i + (i >>> 16);return i & 0x3f;}
这种做法没有宫水三叶 题解中的具有通用性
public int hammingWeight(int n) {n = (n & 0x55555555) + ((n >>> 1) & 0x55555555);n = (n & 0x33333333) + ((n >>> 2) & 0x33333333);n = (n & 0x0f0f0f0f) + ((n >>> 4) & 0x0f0f0f0f);n = (n & 0x00ff00ff) + ((n >>> 8) & 0x00ff00ff);n = (n & 0x0000ffff) + ((n >>> 16) & 0x0000ffff);return n;}
时间复杂度O(logk)k最大32
这做法我印象里做过,但是具体忘记了哪道题了后续会补
