题目描述:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。你可以假设这两个数字一定存在。
要求时间复杂度是 O(n),空间复杂度是 O(1)。
算法:
解法:Leetcode136. 只出现一次的数字
代码:
class Solution
{
public:
vector<int> findNumsAppearOnce(vector<int> &nums)
{
if (nums.size() < 2)
return {};
int numsXor = 0;
for (int &num : nums)
numsXor ^= num;
unsigned int indexOf1 = FindFirstBit1(numsXor);
int num1 = 0, num2 = 0;
for (int &num : nums)
{
if (isBit1(num, indexOf1))
num1 ^= num;
else
num2 ^= num;
}
return {num1, num2};
}
// 辅函数 - 求出数 x 的最低位的 1 的位数
unsigned int FindFirstBit1(int x)
{
int index = 0;
while (((x & 1) == 0) && index < 8 * sizeof(int))
{
x >>= 1;
index++;
}
return index;
}
// 辅函数 - 判断数 x 的第 indexBit 位是不是 1
bool isBit1(int x, unsigned int indexBit)
{
x >>= indexBit;
return x & 01;
}
};
复杂度分析:
时间复杂度:O(n),其中 n 是数组 nums 的元素个数。
空间复杂度:O(1)。
题目来源:AcWing 74. 数组中唯一只出现一次的数字
题目描述:在一个数组中除了一个数字只出现一次之外,其他数字都出现了三次。请找出那个只出现一次的数字。你可以假设满足条件的数字一定存在。
要求只使用 O(n) 的时间和额外 O(1) 的空间。
我们把数组中的所有数字的二进制表示的每一位都加起来。如果某一位的和能被 3 整除,那么那个只出现一次的数字二进制中对应的那一位是 0,否则是 1。
代码:
class Solution
{
private:
const int BITS = 32;
public:
int findNumberAppearingOnce(vector<int> &nums)
{
int ans = 0;
for (int i = 0; i < BITS; i++)
{
int cnt1 = 0;
for (int &num : nums)
cnt1 += (num >> i) & 01;
if (cnt1 % 3 == 1)
ans |= 1 << i;
}
return ans;
}
};
复杂度分析:
时间复杂度:O(BITS * n),其中 BITS = 32,是 int 类型的位数,n 是数组 nums 的元素个数。
空间复杂度:O(1)。