数组中,每个元素出现n次,只有一个出现m次,找出现m次的元素(0<m<n)
算法一
假设数组A元素类型为long,定义一个长度为32的数组bits
b
i
t
s
[
i
]
:
=
数
组
中
有
多
少
个
元
素
第
i
位
(
二
进
制
位
)
为
1
bits[i]:=数组中有多少个元素第i位(二进制位)为1
bits[i]:=数组中有多少个元素第i位(二进制位)为1
因此
b
i
t
s
[
i
]
%
n
=
{
1
出
现
m
次
的
元
素
第
i
位
为
1
0
出
现
m
次
的
元
素
第
i
位
为
0
bits[i] \% n =\begin{cases} 1& 出现m次的元素第i位为1 \\ 0& 出现m次的元素第i位为0 \end{cases}
bits[i]%n={10出现m次的元素第i位为1出现m次的元素第i位为0
实现如下
int findMNumber(vector<long> &A, int n, int m) {
int size = A.size();
int n_bits = 32;
long result = 0;
vector<int> bits(n_bits, 0);
for (int i = 0; i < n_bits; i++) {
for (int j = 0; j < size; j++) bits[i] += (1 & A[j] >> i);
result |= ((bits[i] % n) > 0) << i;
}
return result;
}
算法二
当m小于max(A)时,算法二更快。
int findMNumber2(vector<long> &A, int n, int m) {
int size = A.size();
int n_bits = 0;
long result = 0;
vector<long> bit;
vector<bool> bit_flag;
while (n) {
bit.push_back(0);
bit_flag.push_back(n % 2);
n_bits++;
n /= 2;
}
for (int i = 0; i < size; i++) {
long tmp = A[i];
for (int j = 0; j < n_bits; j++) {
bit[j] ^= tmp;
tmp &= ~bit[j];
}
tmp = ~0;
for (int j = 0; j < n_bits; j++) {
if (bit_flag[j]) tmp &= bit[j];
}
tmp = ~tmp;
for (int j = 0; j < n_bits; j++) {
bit[j] &= tmp;
}
}
for (int j = 0; j < n_bits; j++) {
result |= bit[j];
}
return result;
}