按位异或运算

按位异或运算:

相同为0不同为1,可以理解为无进位加法运算

异或 ^ 的性质:

  1. 0 ^ N = N N ^ N =0 (这里的N指任意的一个整体)
  2. 满足交换律和结合律。
    a ^ b = b ^ a
    (a ^ b) ^ c = a ^ (b ^ c)
  3. 在一堆数据中,只要这些数据不变,不管内部谁与谁先异或,最终结果是一致的(这个性质是由性质1和性质2推出来的)

用异或运算进行两个变量交换位置

int a = 12;
int b = 17;
a = a ^ b;
b = a ^ b;//a = a ^ b , b= a ^ b ^ b =a
a = a ^ b;// a = a ^ b ^ a =b

给你一堆数据,有一个数a出现的次数为奇数,其余的都为偶数,输出这个a

根据异或的性质,我们可以写出这个代码

public static int getNum(int[] nums){
	int num = 0;
	for(int i : nums){
		num = num ^ nums[i];
	}
	return num;
}

给你一堆数据,有两个数a,b出现的次数为奇数,其余的次数为偶数,输出a、b

public class demo {
    public static void main(String[] args) {
        int[] nums = {1, 1, 1, 1, 1, 1, 6, 3, 3, 4, 4, 5, 5, 6, 6, 3};
//        num 用来接收 3 ^ 6
        int num = 0;
//        这里的for循环最好使用下面这种形式,用foreach形式最终结果报错
        for (int i =0 ;i <nums.length;i++) {
            num ^= nums[i];
        }

//        找到3或者6的二进制形式中最右边第一次出现1的位置
        int rightOne = num & ((~num) + 1);

//        定义leftNum用来表示要输出的一个数
        int leftNum = 0;
        
        for(int i =0 ;i <nums.length;i++){
//        将rightOne 与 数组里的每个数都进行与运算,会把nums里面的数分为两个集合,3和6会分别出现在两个集合中            
            if((rightOne & nums[i])==0){
                leftNum = leftNum ^ nums[i];
            }
        }
        
        int rightNum = num ^ leftNum;
        System.out.println(leftNum +"\t"+ rightNum);
    }

}

你可能感兴趣的:(日常记录,java)