异或

参考:http://blog.csdn.net/u012050154/article/details/51957530

Q:给出M个正整数,其中M-1个出现了偶数次,1一个出现了奇数次,找出这个数。

     被问到这个问题的时候,我说,把这M各数存在哈希表中,就可以找到那个出现奇数次的数了。然而,这并不是一个好的解法,面试官提示异或。(以下是摘自网络的知识)

     1.按位与(&)【有0则0】

运算规则:0&0=0;0&1=0;1&0=0;1&1=1;

用途:

(1)清零。如果想将一个单元清零,只需与一个各位都为0的数值相与即可。

(2)取出一个数的指定位。与上 一个指定位为1,其余位为0的数值即可。

例:设x=11101100,取x的低四位。令x&00001111=00001100

     2.按位或(|)【有1则1】

运算规则:0|0=0;0|1=1;1|0=1;1|1=1;

用途:

(1)常用来对某些位置1。或上 一个指定位为1,其余位为0的数值即可。

例:设x=11101100,将x的低四位置1。令x|00001111=11101111

     3.异或(^)【同0异1】

运算规则:0^0=0;0^1=1;1^0=1;1^1=0;

用途:

(1)使特定位翻转,异或上 一个要翻转位数为1,其余位为0的数值即可。

例:设x=11101100,将x的低四位翻转。令x^00001111=11100011

(2)与0异或,保留原值。

(3)基于异或运算,不引用新变量,交换两个变量的值

a=a^b;b=a^b;a=a^b(基于加减法还有:a=a+b;b=a-b;a=a-b)

所以,该编程题的解法是:

public class FindOdd {
    public static void main(String[] args) { int[]a={1,1,4,4,4,5,5}; for(int i=1;i<a.length;i++){ a[0]=a[0]^a[i]; } System.out.println(a[0]); } }

 Q2:找出一串数中出现了奇数次的两个数。

思路:

这串数中的所有数字异或,结果必定是出现奇数次的那两个数异或的值,并且不为0,记为resExclusiveOR;

找出resExclusiveOR的第一个为1的那个位,记为indexOf1,将数组中indexOf1位为1的数分为一组num1,indexOf1位为0的数分为一组num2;

分别对num1、num2中的数做异或,其结果就是要找的那两个数。(附代码,源自网络)

public class FindOdd {
    static void findOnce(int[]data,int length){ int num1=0; int num2=0; if(length<2) return; int resExclusiveOR = data[0]; for(int i=1;i<length;i++){ resExclusiveOR^=data[i]; } int indexOf1 = findFirstBitIs1(resExclusiveOR); for(int i=0;i<length;i++){ if(isBit1(data[i],indexOf1)){ num1=num1^data[i]; }else{ num2=num2^data[i]; } } System.out.println(num1+" "+num2); } static int findFirstBitIs1(int r){ int indexBit=0; while((r&1)==0&&(indexBit<32)){ r=r>>1; indexBit++; } return indexBit; } static boolean isBit1(int num,int index){ if(((num>>index)&1)==1) return true; else return false; } public static void main(String[] args) { int[]arr={1,4,4,1,6,6,6,7,8,8,8,7}; findOnce(arr,12); } }

 17.11.9

(1)计算某个正整数中二进制表示中1的个数

方法1:

public static void main(String[] args) {
        int n=7; int count=0; while(n>0) { if((n&1)==1) { count++; } n=n>>1; } System.out.println(count); }

但是该解法存在一个问题:

(补充:

右移:00001010>>2=00000010;10001010>>3=11110001

左移:00001010<<2=00101000;10001010<<3=01010000)

方法 2:

 private static int countBit(int num){
        int count = 0; for(; num > 0; count++) { num &= (num - 1); } return count; }

参考:

http://www.cnblogs.com/hapjin/p/5839797.html

http://www.cnblogs.com/graphics/archive/2010/06/21/1752421.html

(2)判断某个数的第 i 位是0还是1

private static boolean getBit(int num,int b) { return ((num & (1 << b)) != 0); }

猜你喜欢

转载自www.cnblogs.com/alatar16/p/8994738.html
今日推荐