查找数组奇数倍数字
/**
* 查找数组里只有一个奇数倍的数
*
* 类里定义的数据成员称为属性,属性可不赋初值,若不赋初值则JAVA会按上表为其添加默认值;
* 方法里定义的数据成员称为变量,变量在参与运算之前必须赋初值。
*
* 思路:因为数组里只有一个奇数倍的,根据^运算的性质 a^0=a a^a=0
* 1000
* ^ 1011
* 0011
* 这个性质可以理解为相加不进位 如 0+1=1 0+0=0 1+1=0(进位+1,这里只相加不进位,辅助理解下)
* 如果是偶数倍,即为0,最后一定剩下一个奇数倍单个的数,即e=3
*/
public class OneGeJiShu {
public static void main(String[] args) {
//查找出这个数字3
int[] a = {1,1,3,3,3,2,2,2,2};
//jvm负责初始化类的成员变量
//这里e必须实例化,它是主函数里的局部变量,jvm不负责初始化,参与了运算也必须初始化
int e = 0;
for (int i = 0; i <a.length; i++) {
e ^= a[i];
}
System.out.println("奇数倍的数是:" + e);
//--------------------------------
/**
* 如果两个奇数倍数字呐?
* 找出33 55
* 思路:先找出e1=33^55这两个数,这个结果不可能为0,必有一位是1,保证不为0 如 0010
* 对e1进行取反+1之后&运算,
* +1的目的是为了让取反前后最右边(不一定是第一位)有一位相同 (下面最右边相同是第三位)
* 如: 1100
* 取反 0011
* 加一 0100 这样必有一位和1100相同
* & 0100 &的性质:0&0=0 0&1=0 1&1=1
* rightOne = 0100
* 这两个数假设结果是1100,也就是第三位相同,根据a^b的性质,a和b的第三位不同时才会有第三位的1,
* 也就是说,第三位的1只能是a或者b的其中一个
* 根据0100这个数可以把a和b区分开 a或者b 在 &rightOne 只会有两种结果 0和rightOne
* 其它偶数倍也会有区分,等于就是把数组按rightOne分为两大派,偶数倍就算进去也是0
* rightOne可以存放a或者b,只能一个
* e1^rightOne就等于另一个不是rightOne的值
*
*/
int[] b = {11,11,33,55,66,66};
int e1 = 0, otherOne =0;
for (int i = 0; i < b.length; i++) {
e1 ^= b[i];
}
int rightOne = e1&(~e1+1);
for (int num : b) {
if ((num & rightOne) == rightOne){
otherOne ^= num;
}
}
int e2 = e1^otherOne;
System.out.println("这两个奇数倍的数字是:" + e2 + "," + otherOne);
}
}