您的位置:首页 > 其它

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

2015-05-16 20:58 176 查看
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: