leetcode:137. 只出现一次的数字 II
题目
给你一个整数数组 nums
,除某个元素仅出现 一次 外,其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。
进阶:你的算法应该具有线性时间复杂度。 你可以不使用额外空间来实现吗?
示例:
输入:nums = [2,2,3,2]
输出:3
输入:nums = [0,1,0,1,0,1,99]
输出:99
解答 & 代码
依次求每个二进制位的和:假设求第 i 个二进制位
- 如果整个数组所有元素第 i 个二进制位的和为 3 的倍数,那么只出现一次的元素的第 i 个二进制位为 0(因为其余每个元素的二进制位要么是 0,要么是 1,都重复出现 3 次,因此肯定是 3 的倍数)
如果整个数组所有元素第 i 个二进制位的和除 3 余 1,那么只出现一次的元素的第 i 个二进制位为 1
class Solution {
public:
int singleNumber(vector<int>& nums) {
int result = 0;
// 遍历每个二进制位,对数组中所有元素的该位求和
for(int i = 0; i < 32; ++i)
{
int sum = 0; // 第 i 位的和
for(int j = 0; j < nums.size(); ++j) // 遍历数组中的所有元素
{
int bitVal = (nums[j] >> i) & 1; // 第 j 个数的第 i 个二进制位
sum += bitVal;
}
// 若该位的和除 3 余 1,则只出现一次的元素的该位为 1
if(sum % 3 == 1)
result |= (1 << i); // 将答案的第 i 位置 1
}
return result;
}
};
复杂度分析:设数组包含 n 个数
时间复杂度 O(n):外循环遍历 32 位二进制位,来对每一位求和,时间复杂度 = O(32) = O(1);内循环求该二进制位各个数的和,遍历数组中的每个数,时间复杂度 O(n)
- 空间复杂度 O(1):
执行结果:
执行结果:通过
执行用时:8 ms, 在所有 C++ 提交中击败了 60.56% 的用户
内存消耗:9.2 MB, 在所有 C++ 提交中击败了 77.11% 的用户