【剑指offer】面试题十:二进制中 1 的个数
题目:请实现一个函数,输入一个整数。输出该数二进制中 1 的个数。例如把 9 表示成二进制是 1001, 有 2 位是1.因此如果输入 9,该函数输出 2.
此题考查的是二进制和位运算的基本面试题之一。题目不是很难。
解法一:
基本思路
1、将该数字 i 和 1 做与运算,判断 i 的最低位是不是为 1。
2、接着把 1 左移一位得到 2,再和 i 做与运算就能判断 i 的次低位是不是 1 ···
3、重复 2 操作,将 1 反复左移,每次都能判断 i 的其中一位是不是 1 。
4、循环结束的条件为 当 1 左移 n 位的值 flag 大于该数字 i。
代码如下:
1 // numof1.c 2 #include "stdio.h" 3 #include "stdlib.h" 4 5 int numOf1(int n) 6 { 7 int count = 0; 8 int flag = 1; 9 10 while(flag <= n) 11 { 12 if(flag & n) 13 count ++; 14 flag = flag << 1; 15 } 16 return count; 17 } 18 19 int main(int argc, char const *argv[]) 20 { 21 int val = 0, i = 0; 22 23 while(i++ < 10) 24 { 25 val = rand() % 100; 26 printf("%3d's num of 1: %d\n", val, numOf1(val)); 27 } 28 29 return 0; 30 }
循环的总次数为整数二进制的位数。 例如 86 用二进制表示为 1010110,那么该循环的总次数为 7次。
解法二:
整数中有几个 1 就只需要循环几次。例如上面的 1010110,共有 4 位为 1,我们就只需要循环四次就可以了。
具体介绍:
把一个整数(假设为 val)减去 1,再和原整数 val做与运算,会把 val的最右边一个 1 变成 0.那么一个整数的二进制表示中有多少个 1,就可以进行多少次这样的操作。
现在我们以 1010110(86)为例,详细介绍以上思路:
1、将 1010110(86) 减去 1 之后的二进制表示为 1010101(85),将1010101(85)与1010110(86)做与运算,1010110 & 1010101 = 1010100(1还剩3个)
2、将上述得到的结果 1010100 做与步骤1相同的操作,即 先减 1,得到 1010001, 再将1010100 和1010001 做与运算,1010100 & 1010001 = 1010000(1还剩2个)
3、再次重复步骤1,知道与运算的结果变为 0为止;
基于上面所述,我们可以写出如下代码:
1 // numOf1.c 2 #include "stdio.h" 3 #include "stdlib.h" 4 5 int numOf1(int n) 6 { 7 int count = 0; 8 while(n) 9 { 10 n = n & (n-1); 11 count ++; 12 } 13 return count; 14 } 15 16 int main(int argc, char const *argv[]) 17 { 18 int val = 0, i = 0; 19 20 while(i++ < 10) 21 { 22 val = rand() % 100; 23 printf("%3d's num of 1: %d\n", val, numOf1(val)); 24 } 25 26 return 0; 27 }
编译与执行
1 gcc -o main numOf1.c 2 ./main
完毕。