积跬步至千里——算法强化训练(4)位操作的几个实例

1.利用位运算统计二进制中1的个数

int NumberOfOne(int n)
{
	int cnt = 0;
	for (;n>0;n=n>>1)
	  if(n & 0x1) cnt++;
	return cnt;
}

int NumberOfOne2(int n)
{
	int cnt = 0;
	while (n)
	{
		cnt++;
		n = n & (n-1);
	}
	return cnt;
}

2.利用位运算做加法

如果不考虑进位,两个二进制的相加,便是两个数异或,但是如果存在进位,则结果还要和进位在异或,直到没有进位为止。以5(101)加上17(10001)为例 第一步 10100 但是有进位(00001<<1)  第二步 10100和00010异或 10110 无进位,则结果10110(22)

int Add(int a,int b)
{
	int sum,carry;
	do 
	{
		sum = a ^ b;
		carry = (a & b)<<1;

		a = sum;
		b = carry;
	} while (b!=0);
	return a;
}

3.其它用处

   比如交换两个数  找出一组数中唯一出现的数字 唯一出现的两个数字等等题目

   一个数组中,只有两个数字各出现1次,其它都出现两次

   思路:我们知道,两个相同的数字异或结果为0,0与其他数异或等于其他数,那么这组数字异或的结果等于这两个只出现1次的两个数异或,分析这个结果,这个结果的二进制表示中从右往左肯定有一位不为零,则这两个数字一个和结果一样这一位不为零,另一个这一位为零。即选出数字

void FindTheTwo(vector<int> &data)
{
	int len = data.size();
	int temp = 0,i,j ;
	int answer1 = 0, answer2 = 0;
	for (i = 0; i < len; ++i)
	   temp = temp ^ data[i];
	for (j = 0; j < 32; ++j)//找到temp中不为零的位置
	   if(temp>>j && 0x1 == 1) break;
	for (i = 0; i < len; ++i)
	{
		if(data[i]>>j & 0x1) answer1 ^= data[i];
		else answer2 ^= data[i];
	}
	cout<<"The Two Numbers are "<<answer1<<" "<<answer2<<endl;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值