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

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


对于一个字节(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)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值