一.异或介绍
或者,一种基于二进制的位运算,由符号XOR或^表示,其中运算符两侧数的每个位的等值取0,等值取1。
性质
1、交换规律
2、结合律(即(a^b ) c==a ^ (b ^ c ) ) )
3、对于任何数量x,都有x^x=0、x^0=x
4、自反性A XOR B XOR B=AXOR0=A
二.异或的使用
异或运算在多项式除法运算中最常见,但最重要的性质是自反性。 A^ B^ B=A,即对于给定的数a,用同一运算符(b )进行两次异或运算也能得到a本身。
例如,所有程序教科书都指出,要交换两个变量的值,必须引入中间变量。 但是,使用异或可以节省变量的存储空间。 如果有a、b两个变量,分别存储a、b的值,则以下三行公式交换值表达式(值)。
A=A^ B
B=B ^ A
A=A ^ B
示例:
int a=10,b=5;
a=a ^ b;
b=a ^ b;
a=a ^ b;
同样,该运算可应用于加密、数据传输、验证等多个领域。
三.应用实例
问题:1-1000位于包含1001个元素的数组中,但只有唯一的元素值重复,其他只出现一次。 数组元素只能访问一次。 设计算法,找到它。 是否可以在不使用辅助存储空间的情况下设计算法实现?
解法一(显然已经提出了很好的解法。 请把所有的数加起来,减去1 ) 2…1000之和。 这个算法足够完美,我相信出题人的标准答案就是这个算法。 唯一的问题是数列太大可能会溢出。
解法2 )异或没有这个问题,性能更好。 对所有数进行异或,对得到的结果和1^2^3^.^1000的结果进行异或,得到的结果为重复数。
虽然这个算法很简单,但要证明并不是一件容易的事。 这与异或运算的一些特性有关。 首先是异或运算满足交换律、结合律。
因此,无论这两个n出现在哪个位置,1^2^.^n^.^n^.^1000都可以转换为1^2^.^1000^(n^n )的形式。
其次,对于任何数x,都有x^x=0、x^0=x。
因此,1 ^2^ . ^ n ^ . ^ n ^ . ^ 1000=1^2^ . ^ 1000 ^ (n ^ n )=1^2^.^1000^0=1^2^.^1000
,设1^2^.^1000 (数组不含n )的结果为t
那么,1^2^.^1000 (数组中包含n )的结果就是T^n。
t^(t^n )=n。
所以,取所有数异或得到的结果和1^2^3^.^1000的结果异或得到的结果就是重复数。
当然,也有人说1(2) ) 1000的结果有高斯定律,所以可以快速计算,但实际上1^2^…) ^1000的结果也有定律,算法要比高斯定律简单得多。
谷歌问题变形:一个数组包含几个整数。 一个数出现奇数次,剩下的数出现偶数次。 找到这个奇数次出现的次数吗?
解法有很多,最好的是和上面一样,把所有的数异或,最后的结果是找。 原理是一样的。 代码如下。
公共语音fun () {
inta [ ]={ 22、38、38、22、22、4、4、11、11 };
int temp=0;
for(intI=0; i a.length; I ) {
temp ^=a[i];
}
system.out.println(temp );
}
四、交换两个数的三种方法
int a=5,b=10;
a=a b; //a=15,b=10
b=a-b; //a=15,b=5
a=a-b; //a=10,b=5
但是,这有缺点。 假设在vc6环境中运行,则int的大小为4字节。 因此,int变量中存储的最大值为2^31-1,即2147483647。 如果a的值为2147483000,b的值为1000000000,则a和b相加会越界。
实际上,从实际执行统计数据来看,发现交换的两个变量编号相同的概率很高。 另外,他们之间很少减法运算,也很少越界,所以通过调换上述加减运算,可以减少程序出错的概率。
int a=5,b=10;
a -=b; //a=-5,b=10
b =a; //b=5,a=-5
a=b - a; //a=10,b=5
通过以上的运算,a和b的值交换。 表面上看起来很简单,但特别是在习惯了第三变量算法的引入之后就很难想了。
其原理是将a、b视为轴上的点,以2点之间的距离为中心进行计算。
具体过程:第一句“a-=b”求出ab2点的距离,并将其保存在a中; 第二个句子“b=a”求出从a到原点的距离(从b到原点的距离和ab2点之间的距离的差),并将其保存在b中; 第三句“a=b”求出从b到原点的距离(从a到原点的距离和AB2点的距离之和),保存在a中。 交换完毕。
参考文献:https://www.cn blogs.com/JH sond/p/6374397.html