前言
刚翻开《编程之美》, 中间就有一道我很眼熟的题,“求二进制中1的个数”。书中的题目描述如下:
对于一个字节(8 bit)的无符号整型变量,求其二进制表示中“1”的个数,要求算法执行效率尽可能高。
这当然是一道比较简单的题目,而我在LeetCode上也做过这道题——
Number of 1 Bits: https://leetcode.com/problems/number-of-1-bits/
Write a function that takes an unsigned integer and returns the number of ’1’ bits it has (also known as the Hamming weight).
For example, the 32-bit integer 11 has binary representation “00000000000000000000000000001011”, so the function should return 3.
虽然题目本身,但鉴于此题十分经典,且做法较多,我们在此把(我所知道的)各种可能的方案都讨论一下。
分析与解答
首先想到的一种方案大概就是一直除以2然后统计,先给个例子:
对于10100010(bin),值为162(Dec),
第一次除以2,商1010001(81),余0;
第二次除以2,商101000(40),余1;
第三次除以2,商10100(20),余0;
第四次除以2,商1010(10),余0;
第五次除以2,商101(5),余0;
第六次除以2,商10(2),余1;
第七次除以2,商1,余0;
第八次除以2,商0,余1;
我们注意到,将数字不断除以2,其实就是不断从最低位开始“丢弃”,如果最低位为1,再除以2的时候就余1,否则余0。那么我们就可以通过不断除以2,并判断模2的值来统计一共有多少个“1”了。
class Solution {
public:
int hammingWeight(uint32_t n) {
int count = 0;
while (n) {
if (n % 2 == 1) {
count++;
}
n /= 2;
}
return count;
}
};
但是上面这种想法明显“朴素”了一点,既然是要对二进制表示操作,直接位运算即可。我们可以不断右移一位,但如何判断最低位是不是1呢?可以将数字和0x1进行“与”运算。这个思路相比第一种解法就更为直接了,而且位运算也比除,余要快。
class Solution {
public:
int hammin