做题笔记:找单独的数问题解析
问题描述
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小C快速找到那个拿了独特数字卡片的同学手上的数字是什么。
要求
- 设计一个算法,使其时间复杂度为 O(n),其中 n 是班级的人数。
- 尽量减少额外空间的使用,以体现你的算法优化能力。
测试样例
- 样例1:
cards = [1, 1, 2, 2, 3, 3, 4, 5, 5],输出:4 - 样例2:
cards = [0, 1, 0, 1, 2],输出:2 - 样例3:
cards = [7, 3, 3, 7, 10],输出:10
约束条件
- 1 ≤ cards.length ≤ 1001
- 0 ≤ cards[i] ≤ 1000
- 班级人数为奇数
- 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次
思路
数据结构选择
由于题目要求时间复杂度为 O(n),并且尽量减少额外空间的使用,我们可以考虑使用位运算来解决这个问题。
算法步骤
-
异或运算:异或运算有一个非常有用的性质:
- 任何数和 0 做异或运算,结果仍然是原来的数,即
a ^ 0 = a。 - 任何数和其自身做异或运算,结果是 0,即
a ^ a = 0。 - 异或运算满足交换律和结合律,即
a ^ b ^ a = (a ^ a) ^ b = 0 ^ b = b。
- 任何数和 0 做异或运算,结果仍然是原来的数,即
-
利用异或运算:我们可以遍历整个列表,将所有数字进行异或运算。由于其他数字都出现两次,它们会相互抵消,最终剩下的就是唯一出现一次的数字。
图解
假设输入 cards = [1, 1, 2, 2, 3, 3, 4, 5, 5]:
- 初始
result = 0 - 第一次循环:
result = 0 ^ 1 = 1 - 第二次循环:
result = 1 ^ 1 = 0 - 第三次循环:
result = 0 ^ 2 = 2 - 第四次循环:
result = 2 ^ 2 = 0 - 第五次循环:
result = 0 ^ 3 = 3 - 第六次循环:
result = 3 ^ 3 = 0 - 第七次循环:
result = 0 ^ 4 = 4 - 第八次循环:
result = 4 ^ 5 = 1 - 第九次循环:
result = 1 ^ 5 = 4
最终 result 的值为 4,即唯一出现一次的数字。
代码详解
public class Main {
public static int solution(int[] cards) {
// 初始化结果为0
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);
}
}
#### 代码解释
-
初始化结果:
int result = 0;- 初始化
result为0。
- 初始化
-
遍历列表:
for (int card : cards)- 使用增强型
for循环遍历cards数组中的每个元素,将其赋值给变量card。
- 使用增强型
-
异或运算:
result ^= card;- 对
result和当前的card进行异或运算,并将结果赋值回result。
- 对
-
返回结果:
return result;- 返回
result,即唯一出现一次的数字。
- 返回
总结知识点
-
异或运算:
a ^ 0 = aa ^ a = 0- 异或运算满足交换律和结合律
-
时间复杂度:O(n)
- 遍历一次数组,时间复杂度为 O(n)。
-
空间复杂度:O(1)
- 只使用了常数级别的额外空间。
梳理分析
- 问题理解:找到唯一出现一次的数字。
- 数据结构选择:使用位运算。
- 算法步骤:遍历数组,对每个元素进行异或运算。
- 优化:通过异或运算,避免了使用额外的空间。
学习建议
-
理解异或运算:
- 异或运算在处理重复元素时非常有用,建议多练习相关的题目。
-
时间复杂度分析:
- 理解并分析算法的时间复杂度,确保算法在给定约束条件下能够高效运行。
-
空间复杂度优化:
- 尽量减少额外空间的使用,提升算法的效率。
-
多练习:
- 通过多做类似的题目,加深对异或运算和位运算的理解。