异或

参考: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);
    }
posted @ 2018-05-05 14:55  liumy  阅读(6042)  评论(0编辑  收藏  举报