位运算的巧妙用法

例1:在一个数组中若一个数只出现了一次其它的数都出现的了两次那么如何才能快速的找到这个数

  方法:从前向后两个数依次进行异或最后的结果就是要找的那个数

若数组中的数字依次为 :5,6,4,2,2,5,6 

首先将 5,6进行异或  结果 011  011和4进行异或 111 111和2进行异或 101 101和2进行异或111 111和5进行异或010 010 和6进行异或是100 结果为4 

经过上述的运算我们不难发现两个相同的数进行异或就会互相消除那么最后就会留下那个单独的数

例2:那么如果这个数组中单独的数不止一个那么我们该怎么做才能找出这两个数呢?

根据上个题的做法我们要是从前向后进行异或那么我们得到的一定是这两个只出现一次的数的结果那么我们如何将这两个数进行分离 ?

假如上面的数组中还有一个数是3那么现在的数组中就存在两个单独的数了 我们再将前面的结果与3进行异或我们何以得到结果为111  这个异或的结果代表什么意思?代表这两个单独的数二进制中(1,2,4)这三个位都不一样那么我们可以任选其中的一位对整个数组进行分组 我们可以选择(1)位为1的为一组 (1)位为0的分为一组这样我们就将单独出现的而个数分为了不同的两组

即 5 5 3 为一组   2 2 4 6 6 为一组这样我们就将这个问题转化成了若有一个数出现一次的问题

例3:不用加减乘除法实现两个数的加法运算

首先看十进制是如何做的: 5+7=12,三步走
第一步:相加各位的值,不算进位,得到2。
第二步:计算进位值,得到10. 如果这一步的进位值为0,那么第一步得到的值就是最终结果。第三步:重复上述两步,只是相加的值变成上述两步的得到的结果2和10,得到12。同样我们可以用三步走的方式计算二进制值相加: 5-101,7-111 第一步:相加各位的值,不算进位,得到010,二进制每位相加就相当于各位做异或操作,101^111。第二步:计算进位值,得到1010,相当于各位做与操作得到101,再向左移一位得到1010,(101&111)<<1。第三步重复上述两步, 各位相加 010^1010=1000,进位值为100=(010&1010)<<1。继续重复上述两步:1000^100 = 1100,进位值为0,跳出循环,1100为最终结果。

例四:不用中间变量交换两个数

void swap(int& a, int& b)              //只用加法、减法、乘法也可以交换两个值
{    a = a + b;
    b = a - b;
    a = a - b;
}
void swap(int& a, int& b)              //使用位运算也可以交换两个值
{    a = a^b;
    b = a^b;
    a = a^b;
}
 

 

猜你喜欢

转载自blog.csdn.net/qq_37163944/article/details/82935704
今日推荐