问题描述
有一堆数字,除了一个数字,其它的数字都是成对出现。班上的每个同学拿一个数字,正好将这些数字全部拿完,问如何快速找到拿了单独数字的同学?
输入格式
- 空格分隔输入所有的数字
输出格式
- 单独的那个数字
输入样例
1 1 2 2 3 3 4 5 5
输出样例
4
题目解析
由于题目要求找出单独的数,因此我们可以想到Java中的异或运算操作,即^=。
^= 是 Java 中的复合赋值运算符,表示异或赋值运算。它结合了异或运算(^)和赋值运算(=)。具体来说,a ^= b 等价于 a = a ^ b。
异或运算(^)的特性
- 交换律:
a ^ b = b ^ a - 结合律:
a ^ (b ^ c) = (a ^ b) ^ c - 自反性:
a ^ a = 0 - 与零的异或:
a ^ 0 = a
异或运算的应用
在处理成对出现的数字时,异或运算非常有用。因为成对出现的数字在异或运算中会相互抵消,最终剩下的就是单独的那个数字。
算法步骤
-
初始化一个变量
result为 0。 -
遍历数组中的每一个元素,并将它们与
result进行异或运算。 -
最终,
result将包含单独的那个数字。
解释
-
solution(int[] cards):
这个方法接收一个整数数组cards,数组中的元素可能成对出现,最终通过异或操作找出那个唯一没有成对的数字。- 我们初始化一个变量
result为0,然后遍历cards数组中的每个数字,进行异或运算result ^= card。由于异或运算的自反性,相同的数字会被抵消,最终结果result就是那个没有成对的数字。
- 我们初始化一个变量
-
main(String[] args):
这里我们测试了两个样例,分别是:new int[]{1, 1, 2, 2, 3, 3, 4, 5, 5},这个数组中的唯一单独数字是4。new int[]{0, 1, 0, 1, 2},这个数组中的唯一单独数字是2。
时间复杂度
- 时间复杂度:O(n),其中 n 是输入数组的长度。我们遍历数组中的每个元素,进行一次异或操作,所以时间复杂度是线性的。
- 空间复杂度:O(1),我们只使用了常数空间来存储
result变量。
总结
使用异或运算解决此问题非常高效,因为它能够消除成对出现的数字,最终剩下的就是那个单独的数字。此方法时间复杂度为 O(n),并且只需要常数级别的空间,适合处理较大规模的数据。
代码实现
public static int solution(int[] cards) {
// Edit your code here
int result = 0;
//异或运算可以消去成对元素
for(int card:cards){
result ^= card;
}
return result;
}
public static void main(String[] args) {
// Add your test cases here
System.out.println(solution(new int[]{1, 1, 2, 2, 3, 3, 4, 5, 5}) == 4);
System.out.println(solution(new int[]{0, 1, 0, 1, 2}) == 2);
}
}