找单独的数 | 豆包MarsCode AI 刷题
在编程的世界里,解决问题的技巧和效率往往决定了代码的质量。今天,我们来探讨一个有趣的问题:在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。除了一个数字之外,所有的数字都恰好出现了两次。我们的任务是帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。这个问题不仅考验了我们对算法的理解,还要求我们在时间和空间复杂度上做出优化。
问题描述
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小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 ≤ 10010 ≤ cards[i] ≤ 1000- 班级人数为奇数
- 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次
解题思路
位运算的巧妙应用
在这个问题中,我们可以利用位运算中的异或(XOR)操作来找到那个唯一的数字。异或操作有一个非常有用的性质:对于任何整数 a,a ^ a = 0,并且 a ^ 0 = a。这意味着,如果我们对数组中的所有数字进行异或操作,成对出现的数字会被抵消掉,最终剩下的就是那个唯一的数字。
代码实现
java
复制代码
public class Main {
public static int solution(int[] cards) {
int res = 0;
for (int i = 0; i < cards.length; i++) {
res ^= cards[i];
}
return res;
}
public static void main(String[] args) {
// 测试样例
System.out.println(solution(new int[]{1, 1, 2, 2, 3, 3, 4, 5, 5}) == 4); // 输出: true
System.out.println(solution(new int[]{0, 1, 0, 1, 2}) == 2); // 输出: true
System.out.println(solution(new int[]{7, 3, 3, 7, 10}) == 10); // 输出: true
}
}
代码解析
-
solution方法:- 初始化一个变量
res为 0。 - 遍历数组
cards,对每个元素进行异或操作,结果存储在res中。 - 最终返回
res,即为那个唯一的数字。
- 初始化一个变量
-
main方法:- 测试了三个样例,验证了
solution方法的正确性。
- 测试了三个样例,验证了
时间和空间复杂度分析
- 时间复杂度:O(n),其中 n 是数组的长度。我们只需要遍历数组一次。
- 空间复杂度:O(1),我们只使用了常数级的额外空间。
总结
通过利用位运算的特性,我们能够高效地解决这个问题,不仅满足了时间复杂度的要求,还最大限度地减少了额外空间的使用。这种方法不仅简洁,而且在实际应用中也非常实用。希望这篇文章能帮助你更好地理解和掌握这一技巧。如果你有任何问题或建议,欢迎在评论区留言讨论!