题目
方法一-哈希表
算法思路
遍历数组,用哈希表记录每个数字出现的次数,然后遍历哈希表找到值为1的数字。
具体代码
class Solution {
public int singleNumber(int[] nums) {
int res = 0;
Map<Integer, Integer> map = new HashMap<>();
//构造<数字,出现的次数>哈希表
for(int num : nums){
if(map.containsKey(num)){
map.replace(num, -1);
}else{
map.put(num, 1);
}
}
//遍历哈希表找到只出现1次的数字
for(Map.Entry<Integer, Integer> d : map.entrySet()){
if(d.getValue() == 1)res = d.getKey();
}
return res;
}
}
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n 为数组中元素个数。
- 空间复杂度: O ( l o g n ) O(logn) O(logn),重复出现3次的数字在哈希表中只占一位。
方法二-位运算
算法思路
将所有数字的二进制形式的每一位分别加起来,若某一位的和可以被 3 整除,说明只出现一次的数字在该位上的值为 0 ;若某一位的和不能被 3 整除,说明只出现一次的数字在该位上的值为 1。
具体代码
class Solution {
public int singleNumber(int[] nums) {
if(nums.length == 0)return -1;
int[] bitSum = new int[32];
int res = 0;
//记录所有数字各二进制位上1的出现次数
for(int num : nums){
int mask = 1;
for(int i = 31; i >= 0; i--){
if((num & mask) == mask){
bitSum[i]++;
}
mask <<= 1;
}
}
//将bitSum数组中各二进位的值恢复到res上
for(int i = 0; i < 32; i++){
res <<= 1;
res += bitSum[i] % 3;
}
return res;
}
}
注意:在统计各二进制位上1出现的次数时,除了用上面的方法,也可以通过num
的无符号右移来实现,但这样会修改原数组nums
的数据
复杂度分析
- 时间复杂度: O ( n ) O(n) O(n),n 为数组中元素个数。
- 空间复杂度:
O
(
1
)
O(1)
O(1),
bitSum
长度恒为32。