问题描述
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。
要求:
- 设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。
- 尽量减少额外空间的使用,以体现你的算法优化能力。
测试样例
样例1:
输入:
cards = [1, 1, 2, 2, 3, 3, 4, 5, 5]
输出:4
解释:拿到数字 4 的同学是唯一一个没有配对的。
样例2:
输入:
cards = [0, 1, 0, 1, 2]
输出:2
解释:数字 2 只出现一次,是独特的卡片。
样例3:
输入:
cards = [7, 3, 3, 7, 10]
输出:10
解释:10 是班级中唯一一个不重复的数字卡片。
约束条件
- 1 ≤ cards.length ≤ 1001
- 0 ≤ cards[i] ≤ 1000
- 班级人数为奇数
- 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次
答案
public class Main {
public static int solution(int[] cards) {
// 初始化一个变量用于存储结果
int result = 0;
// 遍历数组中的每一个数字
for (int card : cards) {
// 对每个数字进行异或运算
result ^= card;
}
// 返回最终结果
return result;
}
public static void main(String[] args) {
// 添加你的测试用例
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);
}
}
解析
1.了解异或( ^ )
异或运算的特性
- 相同数字异或结果为 0:即
a ^ a = 0
。 - 任何数字与 0 异或结果为该数字本身:即
a ^ 0 = a
。 - 异或运算满足交换律和结合律:即
a ^ b ^ c = a ^ (b ^ c) = (a ^ b) ^ c
。 - 如果两个对应位上的值不同(一个是 0,另一个是 1),则结果为 1。
-
示例
假设我们有两个不同的数字
a
和b
:
如果a = 5
(二进制表示为0101
)
如果b = 3
(二进制表示为0011
)
那么a ^ b
的结果是:
2.问题理解
你需要在一个整数数组中找到唯一一个出现一次的数字。数组中的其他数字都恰好出现两次。
3.算法步骤
- 异或运算:利用异或运算的特性,即
a ^ a = 0
和a ^ 0 = a
。这意味着如果我们将数组中的所有数字进行异或运算,最终的结果就是那个唯一出现一次的数字。(因为异或运算满足交换律,可以把成对的放到前面先算,最后就剩 0^
(出现一次的数字)= (出现一次的数字))
4.具体步骤
- 初始化一个变量
result
为 0。 - 遍历数组中的每一个数字,将
result
与当前数字进行异或运算。 - 遍历结束后,
result
就是那个唯一出现一次的数字。
5.循环代码解释
// 遍历数组中的每一个数字
for (int card : cards) {
// 对每个数字进行异或运算
result ^= card;
}
-
遍历数组:
for (int card : cards)
是一个增强的 for 循环,用于遍历数组cards
中的每一个元素。- 在每次循环中,变量
card
会被赋值为数组cards
中的当前元素。
-
异或运算:
result ^= card
是result = result ^ card
的简写形式。- 这行代码的作用是将
result
与当前的card
进行异或运算,并将结果赋值回result
。