位运算中那些神奇的事

        之前也是学了很多数据结构与算法,不过一直没有注重位运算这方面,没想到它还有这么神奇的一面,很多不可能的事情忽然就发生了。接下来让我们认真学习一下吧!

1.不使用辅助空间交换两个变量的值

知识点:A ^ A=0,A ^ 0 = A

分析:假设x=a,y=b;那么需要交换x与y的值

1) 令x= x ^ y =a ^ b,那么要想让y=a,可以利用A ^ A = 0的特性将x中的(a ^ b)消去b,即a ^ b ^ b         (此时 x= a ^ b,y = b)

2) 那么就可以令 y = x ^ y = a ^ b ^ b = a ,至此y得到了原先x的值,

        接下来只需要通过位运算使得x=b即可 (此时x = a ^ b,y = a )

3)令x= x ^ y = a ^ b ^ a =b (至此 x = b ,y = a)

利用Java进行代码实现:  

int x=5,y=8;
x=x^y;	// 此时 x = 5 ^ 8		y = 8
y=x^y;	// 此时 x = 5 ^ 8		y=5 ^ 8 ^8 = 5 
x=x^y;	// 此时 x = 5 ^ 8 ^ 5 = 8 	y = 5 

结论:异或可以去除重复的成对元素

2.不使用辅助空间只访问一次数组就找出重复的那个元素

题目:数组长度1001,1 ~ 1000中有一个数出现2次,其他都出现一次,在不使用辅助空间

           且数组中的每个元素只能访问一次的情况下找到这个重复的元素

知识点:A ^ A =0 ,A ^ 0 = A

分析:假设重复的那个元素为k,如果将数组中所有元素都进行异或,那么将得到如下式子:

        S1 = 1 ^ 2 ^ 3 . . . ^ k ^ k. . . ^ 1000

那么可以利用A ^ A = 0 的性质,给上式子中的每一次数都进行再次异或,即

        S2 = ( 1 ^ 2 ^ 3 . . . ^ k ^ k. . . ^ 1000 ) ^ ( 1 ^ 2 ^ 3 . . . ^ k . . . ^1000 )

             = ( 1 ^ 1 ^ 2 ^ 2 ^ 3 ^ 3 . . . ^ k ^ k ^ k . . . ^ 1000 ^ 1000 )

             = k

Java代码实现如下:

//数组为arr,数组长度为1001,数组为1~1000
int getRepeatNumber(int[]arr){
    
    //1.让数组中每一个数据都进行异或
    int res=arr[0];
    for(int i=1;i<1001;i++){
        res^=arr[i];
    }
    
    //2.让异或后的结果再分别于1~1000进行异或
    for(int i=1;i<=1000;i++){
        res^=i;
    }
    
    return res;
}

 结论:异或可以去除重复的成对元素

3.用一条语句判断整数是否为2的整数次方

  知识点:number & (number-1) 的结果去除了number二进制中最后那位1

 知识点说明:如果 number = 0b11100,那么number-1=0b11011

            number                 :     1 1 1 0 0
        
            number-1            :      1 1 0 1 1
        
        number & (number-1) 1 1 0 0 0

可以看出number的最后一位1已经被除去,而2的整数次幂在二进制状态下只包含1个1位,如:

            2 ^ 0     :   1
            2 ^ 1    :    0
            2 ^ 2    :    0 0

分析:只需要判断 number & (number-1)的结果是否为0即可

Java代码实现如下:

boolean is2Pow(int number){
    return (number & (number - 1)) == 0
}

结论:number & (number -1) 可以去除二进制最后的1

4.不使用辅助空间找到只出现1次的那个数

题目:数组中只有一个数出现了1次,其他的数都出现了k次,找出只出现一次的数

知识点:k个number在k进制下做不进位加法运算得到的结果为0

        这个知识听起来有点绕,不过别急,听小小李一点点分析之后你一定觉得很简单!

知识点解析

        1)不进位加法运算:

                        如 8+5=13 省去进位的1 即 8+5=3即为不进位运算

        2)k个number在k进制下做不进位加法:

                        如十进制下:10个8相加=80丢弃进位的8,即8+8+...+8=0

分析:   用这个结论将数组中所有元素进行不进位加法运算的结果为出现1次的那个数,

        出现k次的数做不进位加法之后结果为0,所以除了只出现1次的那个数,其他的数

        相加的结果为0

Java代码实现:

//找到只出现1次的那个数
int getMeetOneNumber(int[]arr,int k){
    char[][]kRadix=new char[arr.length][];
    int maxLen=0;
    //将数组中的数转换为k进制并反转
    for (int i = 0; i < arr.length; i++) {
         kRadix[i]=new StringBuffer(Integer.toString(arr[i],k)).reverse().toString().toCharArray();
         if (kRadix[i].length>maxLen)
            maxLen=kRadix[i].length;
    }
    int[]resArr=new int[maxLen];
    //将数组中所有数对应位进行不进位加法运算
    for (int i = 0; i < kRadix.length; i++) {
        for (int j = 0; j < resArr.length; j++) {
            if (j<kRadix[i].length)
              resArr[j]= (resArr[j] + kRadix[i][j]-'0')%k;
        }
    }
    //最终resArr里面储存的就是只出现1次的那个数的k进制,转换为10进制返回即可
    int res=0;
   	for (int i = 0; i < resArr.length; i++) {
        res+= (resArr[i]%k)*Math.pow(k,i);
    }
    return res;
}

  结论:k个number在k进制下做不进位加法运算得到的结果为0

总结

        结论1:异或可以去除重复的成对元素

        结论2:number & (number -1) 可以去除二进制最后的1

        结论3:k个number在k进制下做不进位加法运算得到的结果为0

  • 22
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值