位运算的相关内容
交换两个数
-
当交换两个数时,一般情况下会开一个额外变量作为中介,或者是使用C++的swap,也或者利用数学特性进行交换
int tmp=x; //额外变量 x=y; y=tmp; swap(x,y); //调用swap x=x+y; //数学 y=x-y; x=x-Y
同时我们也知道,异或:相同为假,不同为真。两个相同的数异或之后等于0,任何数与0异或等于其本身,所以我们可以推导出以下交换两个数的式子
异或是支持交换律和结合律的x=x^y; y=x^y; x=x^y;
仔细一看,三个式子中全部都带有x^y,做一下解释,第一个式子中将x^y的结果赋给了x,对于第二个式子,将第一个结果带入可得:x=x^y=(x^y)^y=x^(y^y)=x^0=x,这样就将x的值赋给了y,同理,第三个式子就将y的值赋给了x
找出没有重复的数
-
例如:给你一串整型数,这些数中有的数重复出现了两次,但只有一个数出现了一次,让你求出这个数。
前几条已经知道:两个相同的数异或结果为0,任何数与0异或都等于其本身。这样思路大致就有了:我们让所有的数都异或一遍,相同的数通过异或会等于0,0再与其他数字异或还是等于那个数字,所以最后异或结果就是那个只出现一次的数字了int search(int a[],int len) { int ans=a[0]; for(int i=1;i<len;i++) ans^=a[i]; return ans; }
快速幂
-
快速幂也是用到了与运算的内容,这里就不多讲了
求不大于N的最大的2的幂指数
-
朴素做法:
int search(int N) { int ans=1; for(int i=1;ans<=N;i++) ans*=2; return ans/2; }
我们也可以通过位运算来求解
例如12的二进制为:00001100,我们要求的是:00001000的十进制为8,所以要求的数即为N的二进制表示中保留最高为1,其余变为0即可,下面给出代码N|=N>>1; N|=N>>2; N|=N>>4; N|=N>>8; N|=N>>16; //32、64不同 ...
这样N二进制表示中最左边1右边所有的数都变为了1,即00001111,再让N>>1,整体右移一位,变为了00000111,然后N+1,变为了00001000,即为我们要求的数;也可以对00001111先+1,然后>>1,
总代吗:
int search(int N) { N|=N>>1; N|=N>>2; N|=N>>4; N|=N>>8; N|=N>>16; return (N+1)>>1; }
如有出错之处,请您通知本人,本人将以感激的态度接受您的指正。