题目链接
剑指 Offer II 004. 只出现一次的数字 mid
题目描述
给你一个整数数组 nums
,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
示例 1:
输入:nums = [2,2,3,2]
输出:3
示例 2:
输入:nums = [0,1,0,1,0,1,100]
输出:100
提示:
- 1 < = n u m s . l e n g t h < = 3 ∗ 1 0 4 1 <= nums.length <= 3 * 10^4 1<=nums.length<=3∗104
- − 2 31 < = n u m s [ i ] < = 2 31 − 1 -2^{31} <= nums[i] <= 2^{31} - 1 −231<=nums[i]<=231−1
nums
中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
解法一:
第一次遍历用一个哈希表记录数组中元素的出现次数,第二次遍历就找到那个出现次数为 1 的元素,返回该元素即可。
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( n ) O(n) O(n)
C++代码:
class Solution {
public:
int singleNumber(vector<int>& nums) {
unordered_map<int,int> cnt;
for(auto &x:nums) cnt[x]++;
int ans = -1;
for(auto &[k,v]:cnt){
if(v == 1){
ans = k;
break;
}
}
return ans;
}
};
Java代码:
class Solution {
public int singleNumber(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
for (int x : nums) {
map.put(x, map.getOrDefault(x, 0) + 1);
}
for (int x : map.keySet()) {
if (map.get(x) == 1) return x;
}
return -1;
}
}
解法二:
因为数组中的每一个元素都是32位整数,所以我们可以用一个长度为32 的 bit 数组来记录所有的元素。
因为数组中只有一个元素只出现了一次,其他都出现了三次。
所以如果我们对 b i t [ i ] ( 0 < = i < 32 ) bit[i] (0<=i<32) bit[i](0<=i<32) 都 %3,剩下的就是那个只出现一次的数字的二进制位了。
例如:
nums = [2,2,2,3,3,3,5]
时间复杂度: O ( n ) O(n) O(n)
空间复杂度: O ( 1 ) O(1) O(1)
C++代码:
class Solution {
public:
int singleNumber(vector<int>& nums) {
vector<int> bit(32);
for(auto &x:nums){
for(int i = 0;i < 32;i++){
bit[i] += (x >> i) & 1;
}
}
int ans = 0;
for(int i = 0;i < 32;i++){
ans += (bit[i] % 3) << i;
}
return ans;
}
};
Java代码:
class Solution {
public int singleNumber(int[] nums) {
int[] bit = new int[32];
for(int x:nums){
for(int i = 0;i < 32;i++){
bit[i] += (x >> i) & 1;
}
}
int ans = 0;
for(int i = 0;i < 32;i++){
ans += (bit[i] % 3) << i;
}
return ans;
}
}