求二进制数中"1"的个数

来源:互联网 发布:里程 积分 知乎 编辑:程序博客网 时间:2024/06/06 01:00

本题同样来自《编程之美》。


对于一个字节(8bit)的无符号整型变量,求其二进制表示中“1”的个数。


笨方法:

对于二进制操作,除以一个2,原来的数字就会减少一个0.(可以类比十进制,十进制除以一个10,则相应会减少一个0)

如果除的过程中有余,那么就表示当前位置有一个1.

#include<stdio.h>typedef unsigned char BYTE;int Count(BYTE v){int num = 0;while(v){if(v%2==1)num++;v=v/2;}return num;}int main(){BYTE b1 = 0;BYTE b2 = 129;BYTE b3 = 255;printf("b1 :%d\n",Count(b1));printf("b2 :%d\n",Count(b2));printf("b3 :%d\n",Count(b3));return 0;}


好方法:

右移操作同样可以达到相除的目的。

右移后,与00000001进行“与”操作。

int Count(BYTE v){int num = 0;while(v){num+=v&0x01;v>>=1;}return num;}



聪明方法:

虽然使用位操作的效率比笨方法高多了,但是,时间复杂度仍为O((log2)v)。

想办法使时间复杂度只与“1”的个数相关。

若v为:01000000,则v-1为:00111111。两者相与为0。

若v为:01100000,则v-1为:01011111。两者相与为01000000。此时和第一种情况一样。再次操作后,为0。

所以,根据这个规律,我们考虑v和v-1相与,统计结果为0之前的次数即为“1”的个数。

int Count(BYTE v){int num = 0;while(v){v&=(v-1);num++;}return num;}


此外,还有空间换时间的方法。

将所有的256种情况存储在数组中。

根据v的不同,直接取相应的情况即可。

算法时间复杂度仅为O(1)。


0 0
原创粉丝点击