异或运算算法

1异或运算法则

异或运算:相同为0,不同为1
异或运算就记成无进位相加。
满足交换律,结合律。
0^N = N
N^N = 0

int a = 7; //  00111
int b = 13; // 01101
			   01010 = 8+2 = 10

2不用任何空间的情况下交换两个变量

内存区域不同,可以使用这个方法:

int a = 13;
int b = 7;

a = a^b;
b = a^b;
a = a^b;
---> a = 7; b = 13;
解释:
a = a^b; // a = a^b; b = b;
b = a^b; // a = a^b; b = a^b^b = a^ (b^b) = a^0 = a;
a = a^b; // a = a^b^a = a^a^b = 0^b = b;

3一个数组中有一种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这种数

相同为0,交换律。
[a, b, c, d, e, ...]
int eor = 0;
eor = eor^a;
eor = eor^b;
eor = eor^c;
eor = eor^d;
...
eor = eor^...;

4怎么把一个int类型的二进制数,提取出最右侧的1

a = 01101110010000
ans= 00000000010000

a =  01101110010000
~a=  10010001101111
~a+1=10010001110000

a & (~a+1)
=a & (-a)
= 00000000010000

5一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数(奇数次)

这两种奇数为a,b:
eor = 0;
eor = eor^...
	= a^b != 0; //因为a != b;
所以:eor的某一位状态为1,利用算法第四题找到这个状态位1。
所以,可以将所有的数分为:
1、最右侧的是12、最右侧的是0: 两种。
eor1 = 0; eor1 ^ ...(第一种的数) = a(假设);
eor^eor1 = b;
// arr中,有两种数,出现奇数次
    public static void print0ddTimesNum2(int[] arr) {
    
    
        int eor = 0;
        for (int i = 0; i < arr.length; i++) {
    
    
            eor ^= arr[i];
        }
        // a和b是两种数
        // eor. != 0
        // eor最右侧的1,提取出来
        // eor :00110010110111000
        // rightOne : 000000000001000
        int rightOne = eor & (-eor); //提取出最右的1
        int onlyOne = 0; // eor'
        for (int i = 0 ; i < arr.length; i++) {
    
    
            // arr[1] = 111100011110000
            // rightOne= 00000000010000
            if ((arr[i] & rightOne) != 0) {
    
    
                onlyOne ^= arr[i];
            }
        }
        System. out. println(onlyOne +" " + (eor ^ onlyOne));
    }

6 一个数组中有一种数出现K次,其他数出现了M次(M>1,K<M),找到出现了K次的数,要求:额外空间复杂度0(1)

定义一个int[] t = new int[32]; //存储二进制的每一位数
将数组中的每一个数转为二进制表示,t数组的每一位累加;
累加完成之后,数组每一位与M% 运算;
不是0的位,则为出现k次的数二进制位1的位。
package entity;

/**
 * @email [email protected]
 * @author: zhaoshuai
 * @date: 2021/8/8 7:15
 */
public class Soultion {
    
    
    public static void onlyKTimes(int[] arr, int k, int m) {
    
    
        int[] t = new int[32];
        // t[0]:0位置的1出现了几个
        for (int num : arr) {
    
    
            for (int i = 0; i <= 31; i++) {
    
    
                // 依次提取出每一位的状态
                if (((num >> i) & 1) != 0) {
    
    
                    t[i]++;
                }
            }
        }
        int ans = 0;
        for (int i = 0; i < 31; i++) {
    
    
            if (t[i] % m != 0) {
    
    
                ans |= (1 << i);
            }
        }
        System.out.println(ans);
    }
}

猜你喜欢

转载自blog.csdn.net/zs18753479279/article/details/119505072
今日推荐