001.异或运算

001.异或运算数据结构与算法学习笔记 异或运算相同为

大家好,欢迎来到IT知识分享网。

认识异或运算

异或运算:相同为0,不同为1

同或运算:相同为1,不同为0

能长时间记住的概率接近0%

所以,异或运算就记成无进位相加

异或运算的性质

1)0 ^ N == N N ^ N == 0

2)异或运算满足交换律和结合律

​ 相当于几个数在一起进行异或运算 不论数的顺序是否相同 得到的结果都是一样的

如下例子:

a b c 结果
1 0 1 0
0 0 1 1
1 1 1 1
1 0 0 1

上面的表格可以看出来,无论你的顺序是 a ^ b ^ c 还是 b ^ c ^ a 还是 b ^ a ^ c 等 得到的结果都是一样的,因为每一个位置上的结果与 a b c 对应位置的值有关,与其它位置无关。

上面的两个性质用无进位相加来理解就非常的容易

题目一 如何不用额外变量交换两个数

这种方式的前提是两个变量指向的内存不同才可以进行交换,否则计算处理等于0

int a = 甲 , int b = 乙;

a = a ^ b;

b = a ^ b;

a = a ^ b ;

最后的结果就是 a = 乙,b = 甲

证明:

int a = 甲 , int b = 乙;

a = a ^ b = 甲 ^ 乙

b = a ^ b = (a ^ b) ^ b = a ^ b ^ b = 甲 ^ 乙 ^ 乙 = 甲 ^ 0 = 甲

a = a ^ b = (a ^ b) ^ 甲 = 甲 ^ 乙 ^ 甲 = 乙

所以 a = 乙,b = 甲

public static void main(String[] args) { 
    int a = 300; int b = 345; System.out.println("---交换之前---"); System.out.println("a = " + a); System.out.println("b = " + b); a = a ^ b; b = a ^ b; a = a ^ b; System.out.println("---交换之后---"); System.out.println("a = " + a); System.out.println("b = " + b); // 数组里面的值进行交换 int[] arr = { 
   3,1,100}; System.out.println("---交换之前---"); System.out.println("arr[0] = " + arr[0]); System.out.println("arr[2] = " + arr[2]); swap(arr, 0 , 2); System.out.println("---交换之后---"); System.out.println("arr[0] = " + arr[0]); System.out.println("arr[2] = " + arr[2]); } public static void swap(int[] arr, int i , int j) { 
    arr[i] = arr[i] ^ arr[j]; arr[j] = arr[i] ^ arr[j]; arr[i] = arr[i] ^ arr[j]; } 运行结果如下: ---交换之前--- a = 300 b = 345 ---交换之后--- a = 345 b = 300 ---交换之前--- arr[0] = 3 arr[2] = 100 ---交换之后--- arr[0] = 100 arr[2] = 3 

特别注意:

这种方式的前提是两个变量指向的内存不同才可以进行交换,否则计算处理等于0

例如:

public static void main(String[] args) { 
    int[] arr = { 
   3,1,100}; System.out.println("---交换之前---"); System.out.println("arr[0] = " + arr[0]); System.out.println("arr[2] = " + arr[2]); swap(arr, 2 , 2); System.out.println("---交换之后---"); System.out.println("arr[2] = " + arr[2]); System.out.println("arr[2] = " + arr[2]); } public static void swap(int[] arr, int i , int j) { 
    arr[i] = arr[i] ^ arr[j]; arr[j] = arr[i] ^ arr[j]; arr[i] = arr[i] ^ arr[j]; } 执行结果: ---交换之前--- arr[0] = 3 arr[2] = 100 ---交换之后--- arr[2] = 0 arr[2] = 0 

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

所有的数都异或运算起来,因为异或运算的结果与数的位置无关,并且其他数出现的次数都是偶数次,只有一种数是奇数次,所以所有的数异或运算之后就是该种数

// arr中,只有一种数,出现奇数次 public static void printOddTimesNum1(int[] arr){ 
    int eor = 0; for (int i = 0; i < arr.length; i++) { 
    eor ^= arr[i]; } System.out.println(eor); } 

题目三 怎么把一个int类型的数,提取出最右侧的1来

例子:

0000

00000000001000

0000

00000000000010

n & ((~n) + 1) n 与 (n取反后再加1)

例如

n = 0 0 0 0 1 1 1 0 1 0 1 0 0 0

~n = 1 1 1 1 0 0 0 1 0 1 0 1 1 1

~n + 1 = 1 1 1 1 0 0 0 1 0 1 1 0 0 0

n & (~n + 1) = 00000000001000

题目四 一个数组中有两种数出现了奇数次,其他数都是出现了偶数次,怎么找到并打印这两种数。

首先进行分析

假设两种出现次数为奇数次的数分别是 a 或 b

那么数组中的数全部进行异或运算之后的结果就是 eor = a ^ b

eor 的结果肯定是不为 0 的(如果为0 表示 a == b)

那么 eor 不为0 的位置 就是 a 和 b 数的不同的位置了。

这里假设 eor = 0

如果为1就代表 a 和 b 数不相同的 位置了

选择其中的一个位置就可以进行区分

这里选择最后一个为1 的位置 0000000100

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZGqIraid-40)(imgs/image-.png)]

然后在进行异或运算之前先判断一下这个位置不等于0的数

如果不为0然后进行异或运算之后的结果就是b

最后进行 eor ^ b = a ^ b ^ b = a

代码如下:

// arr 中,有两种数,出现奇数次 public static void printOddTimesNum2(int[] arr){ 
    int eor= 0; for (int i = 0; i < arr.length; i++) { 
    eor ^= arr[i]; } // eor = a ^ b // eor != 0 // eor 必然有一个位置上是1 int rightOne = eor & (~eor + 1); // 提取出最右的 1 int onlyOne = 0; //eor for (int i = 0; i < arr.length ; i++) { 
    if ((rightOne & arr[i]) != 0) { 
    onlyOne ^= arr[i]; } } System.out.println(onlyOne + " " + (onlyOne ^ eor)); } 

题目五 计算出一个int类型的数中的二进制数为1的个数

该题目就是先找到最右边不为0的值

然后将count++

紧接着就进行异或运算将该位置上的1去掉,然后进行下一次的循环,直到将N赋值为0后就跳出循环,最后得到的结果就是 1 的个数。

public static int bit1Counts(int N){ 
    int count = 0; while (N != 0) { 
    int rightOne = N ^ (~N + 1); count++; N ^= rightOne; } return count; } 

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/158894.html

(0)
上一篇 2025-01-17 15:20
下一篇 2025-01-17 15:25

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信