题目
给你一个整数数组 nums
,除某个元素仅出现 一次 外,其余每个元素都恰出现 **三次 。**请你找出并返回那个只出现了一次的元素。
你必须设计并实现线性时间复杂度的算法且不使用额外空间来解决此问题。
示例 1:
输入:nums = [2,2,3,2]
输出:3
示例 2:
输入:nums = [0,1,0,1,0,1,99]
输出:99
提示:
1 <= nums.length <= 3 * 10^4
-2^31 <= nums[i] <= 2^31 - 1
nums
中,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次
解题
方法一:哈希表
思路
维护一个哈希表(counts
),记录每个数在数组中出现的次数,然后找出出现一次的数字返回即可。
代码
class Solution {
public int singleNumber(int[] nums) {
Map<Integer, Integer> cnts = new HashMap<>();
for (int n : nums) {
if (cnts.containsKey(n)) cnts.put(n, cnts.get(n) + 1);
else cnts.put(n, 1);
}
for (int key : cnts.keySet()) {
if (cnts.get(key) == 1) return key;
}
return 0;
}
}
方法二:位运算
思路
我们可以把数组中的每一个数用二进制的形式来表示,然后把二进制的每一位上 的个数计数,每一位上 的个数必然是 或 ,此时位上计数是 的位就是那个只出现一次的数字的每一位。
例如:nums = [2,2,3,2]
计数:
此时只有第 位和第 位上的计数不能被 整除,那么落单的数的二进制表示就是 也就是 。
而这个方法操作的都是二进制位,所以正负数不会有影响。
代码
class Solution {
public int singleNumber(int[] nums) {
int ans = 0;
for (int i = 0; i < 32; ++i) {
int mask = 1 << i, cnt = 0;
for (int num : nums) {
if ((num & mask) != 0) ++cnt;
}
if (cnt % 3 != 0) ans |= mask;
}
return ans;
}
}
class Solution {
public:
int singleNumber(vector<int>& nums) {
int ans = 0;
for (int i = 0; i < 32; ++i) {
int mask = 1 << i, cnt = 0;
for (int& num : nums) {
if (num & mask) ++cnt;
}
if (cnt % 3) ans |= mask;
}
return ans;
}
};
评论区