// 数组中数字出现的次数:数组中只出现一次的两个数字,其他数字都出现两次(位运算特点:位异或exclusiveOR(^), 位与(&))
// 其他解法:使用排序,然后二分查找只出现一次的数字,时间O(n log n),
// 使用哈希表存储每个数字出现的次数,时间O(n),空间O(n)
int FindFirstBit1(int number){
int indexBit = 0;
while ((number & 1 == 0) && (indexBit < 8 * sizeof(int))){
number = number >> 1;
indexBit++;
}
return indexBit;
}
bool isBit1(int number, int indexBit){
number = number >> indexBit;
return (number & 1);
}
bool g_bInvalid = false;
void FindNumsAppearOnce(int data[], int length, int* num1, int* num2){
g_bInvalid = false;
if (data == nullptr || length < 2){
g_bInvalid = true;
return;
}
int result = 0;
for (int i = 0; i < length; ++i){
result ^= data[i];
}
*num1 = *num2 = 0;
int indexBit1 = FindFirstBit1(result);
for (int i = 0; i < length; ++i){
if (isBit1(data[i], indexBit1))
*num1 ^= data[i];
else
*num2 ^= data[i];
}
}
// 数组中只出现一次的一个数字,其他数字都出现三次:按位求和(长度32的辅助数组),出现三次的数字和能被3整除,时间复杂度O(n), 空间复杂度O(1)
int FindNumAppearOnce(int* data, unsigned int length){
g_bInvalid = false;
if (data == nullptr || length < 4){
g_bInvalid = true;
return 0;
}
int bitSum[32] = {0};
for (int i = 0; i < length; ++i){
int bitMask = 1;
for (int j = 31; j >= 0; --j){
int bit = data[i] & bitMask;
if (bit != 0)
bitSum[j] += 1;
bitMask = bitMask << 1;
}
}
int result = 0;
for (int i = 0; i < 32; ++i){
result = result << 1;
result += bitSum[i] % 3;
}
return result;
}