问题描述
在一个班级中,每位同学都拿到了一张卡片,上面有一个整数。有趣的是,除了一个数字之外,所有的数字都恰好出现了两次。现在需要你帮助班长小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
- 班级人数为奇数
- 除了一个数字卡片只出现一次外,其余每个数字卡片都恰好出现两次
解题思路
-
问题分析:
- 目标是找到在一个数组中只出现一次的数字,而数组中除了一个数字之外,其余的数字都恰好出现了两次。
- 考虑到数组的长度为n,我们需要设计一个时间复杂度为O(n)的算法。
- 空间复杂度应该尽可能优化,尽量减少额外空间的使用。
-
思路设计:
- 使用哈希表(HashMap)记录每个数字出现的次数,遍历数组时更新哈希表。
- 遍历结束后,查找哈希表中出现次数为1的数字,即为我们需要的结果。
- 但是,根据题目要求,我们还需要考虑空间优化。虽然HashMap提供了便利,但理论上我们只需要一个定长的数组来记录数字出现的次数(假设数字范围在0到8之间,这是一个简化的假设,实际使用时需要根据数字范围调整数组大小)。
- 如果我们假设数字范围在0到某个固定值M之间,可以创建一个长度为M+1的数组来计数,这样就不需要额外的哈希表开销。
-
实现细节:
- 如果使用HashMap,代码较为直观,但空间复杂度为O(n)(哈希表的开销)。
- 如果使用定长数组,需要预先知道数字的范围。假设数字范围已知且不大,这种方法能有效减少空间使用。
最终代码:
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static int solution(int[] inp) {
Map<Integer,Integer> map=new HashMap<>();
int[] nums = new int[9];
Arrays.fill(nums,0);
for (int i : inp) {
if(map.containsKey(i) != true){
map.put(i,1);
}else {
map.put(i,map.get(i) + 1);
}
}
return map.entrySet().stream()
.filter(entry -> entry.getValue() == 1)
.map(Map.Entry::getKey)
.findFirst()
.map(key -> (int) key)
.orElse(0);
}
}