问题可能是误导了一点,但我不知道如何以另一种方式提出问题。 hackerrank存在一个问题如下:
考虑一个整数数组,其中只有一个整数 成对出现。换句话说,每个元素恰好发生两次 除了一个独特的元素。
给定数组查找并打印唯一元素。 [2,3,1,3,2] - >结果是1
我解决了这个问题:
private static int lonelyInteger(int[] a) {
if(a==null)
return 0;
if(a.length<2)
return a.length;
Set<Integer> set = new HashSet<>();
for(int i : a){
if(set.contains(i)){
set.remove(i);
}else{
set.add(i);
}
}
return (Integer) set.toArray()[0];
}
然而,我们认为这个问题有一个简洁的解决方案:
private static int lonelyInteger(int[] a) {
int b = a[0];
for(int i = 1; i < a.length; i++){
b ^= a[i];
}
return b;
}
问题是我不知道为什么工作? 我理解它是如何工作但不明白为什么它工作? 要理解我制作了一个小程序来输出每个步骤的结果:
public class BitwiseOperator {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] a = new int[n];
int sum = 0;
in.nextLine();
String line = in.nextLine();
String[] numbers = line.split(" ");
for (int i = 0; i < numbers.length; i++) {
a[i] = Integer.valueOf(numbers[i]);
}
for (int i = 0; i < a.length; i++) {
binary(sum, a[i]);
sum ^= a[i];
binary(sum);
System.out.println();
System.out.println();
System.out.println();
}
System.out.println(sum);
}
private static void binary(int sum) {
System.out.println(String.format("%16s", Integer.toBinaryString(sum)).replace(' ', '0') + " ->" + sum);
}
private static void binary(int sum, int i) {
System.out.println(String.format("%16s", Integer.toBinaryString(sum)).replace(' ', '0') + " ->" + sum);
System.out.println("XOR");
System.out.println(String.format("%16s", Integer.toBinaryString(i)).replace(' ', '0') + " ->" + i);
System.out.println("--------");
}
}
如果输入以下输入:
5
2 3 2 1 3
输出结果为:
0000000000000000 ->0
XOR
0000000000000010 ->2
--------
0000000000000010 ->2
0000000000000010 ->2
XOR
0000000000000011 ->3
--------
0000000000000001 ->1
0000000000000001 ->1
XOR
0000000000000010 ->2
--------
0000000000000011 ->3
0000000000000011 ->3
XOR
0000000000000001 ->1
--------
0000000000000010 ->2
0000000000000010 ->2
XOR
0000000000000011 ->3
--------
0000000000000001 ->1
1
所以该程序实际上是可行的,但我真的需要了解为什么?
答案 0 :(得分:4)
准确的证据,恕我直言,涉及群论(你可以根据xor
建立阿贝尔群组):
xor
是一个群组操作0
是一个群组0
A
是一个反向元素(因此任何A
都与自身相反)。当然,我们必须证明(A xor B) xor C == A xor (B xor C)
由于A xor B == B xor A
我们有一个阿贝尔群组,这就是为什么可以重新组合
任何顺序的项目:
A XOR B XOR C XOR A XOR B ==
(A XOR A) XOR (B XOR B) XOR C ==
C
一般情况下:
A xor B xor ... xor Z ==
(A xor A) xor (B xor B) xor ... xor (distinct Item) ==
0 xor 0 xor ... xor (distinct Item) ==
distinct Item
答案 1 :(得分:1)
考虑一个整数数组,其中除了一个整数之外的所有整数都成对出现。换句话说,除了一个唯一元素之外,其中的每个元素都恰好发生两次。现在假设您添加了所有这些数字。
如果这笔钱是均匀的,这意味着什么?这意味着出现一次的数字必须是均匀的。如果总和是奇数,这意味着什么?这意味着出现一次的数字必须是奇数。想一想,直到你理解它为止。
现在想象一下,我们只是跟踪总和是偶数还是奇数,而不是总结它们。因此,如果前两个数字是3和7,那么总和将是10,但我们只记得它是偶数。这仍然有效。即使出现一次的数字是偶数也是奇数,如果出现一次的数字是奇数,最终的答案就是如此。想一想,直到你理解它为止。
这就是我们如何才能使它适用于一些数字。但我们也可以同时为所有位做到这一点,跟踪每个位的位置,无论总数是奇数还是偶数。完成后,我们会看到一次出现的数字是奇数还是偶数位,这就是我们所需要的。由于我们是以二进制方式进行的,因此该位置唯一的奇数是1,唯一的偶数是0.在你理解之前,请考虑这个。
答案 2 :(得分:0)
我将尝试使其简短而简单。
异或相同的数字将返回0 。
示例: 23 ^ 23 = 0 -325 ^ -325 = 0
因此,当您执行循环的XOR运算时,出现两次的数字将自行抵消,最终您将获得唯一的数字。