1.寻找无序互异数组中丢失1个数。
异或操作相当于逻辑加。
代码:
int Find1(int seq[], int n, int&a)
{
a = 0;
for(int i =0; i < n; i++)
{
a^=seq[i];
}
return 0;
}
2.寻找无序互异数组中丢失2个数。需要将全部数字分成两组A,B,A缺少a,B缺少b。
void Find2(int seq[], int n, int& a, int& b)
{
XOR
int xors = 0;
for(int i = 0; i < n; i++)
xors ^= seq[i];
get different bit
int diff = lowbit(xors);
a = 0;
b = 0;
for(int i = 0; i < n; i++)
{
if(diff & seq[i])
a ^= seq[i];
else
b ^= seq[i];
}
}
2.寻找无序互异数组中丢失3个数。需要分成3组A,B,C,A缺少a,B缺少b,C缺少c。
首先s= a^b^c。
假设s的某一个bit=0
a,b,c有两种情况
z1.1 z1.2
a 1 0
b 0 0
c 1 0
假设s的某一个bit=1
z1.3 z1.4
a 0 1
b 1 1
c 0 1
s中所有的bit生成情况只能是z1.1,z1.2,z1.3,z1.4中的一种。而且z1.1和z1.3的出现次数一定大于2次。否则只有1次的话,s只能由两个数组成。
假设a^b, b^c, c^a任意一bit位
z2.1 z2.2 z2.3 z2.4
a^b 1 1 1 0
b^c 1 1 0 0
c^a 1 0 0 0
因为(a^b)^(b^c)^(c^a)=0 所以z2.1,z2.3不符和。只能出现z2.2,z2.4。
z2.2对应a,b,c状态:
z1.1 z1.3
a 1 0
b 0 1
c 1 0
这种情况可以用于区分a,b,c
z2.4对应a,b,c状态:
z1.4 z1.2
a 1 0
b 1 0
c 1 0
这种情况不能用于区分a,b,c
------------------------------
所以利用z2.2的情况可以用来区分数据。又因为z1.1和z1.3的次数一定>2,所以 z2.2的出现次数一定>2
所以a^b, b^c, c^a某一bit位只能出现1,1,0,这个bit位可以用来区分数据,分组。
假设a^b, b^c, c^a某2个bit位出现1,1,0情况,用来分组。出现两种情况。
z3.1:
bit1 bit2
a^b 1 0
b^c 1 1
c^a 0 1
z3.2:
bit1 bit2
a^b 1 1
b^c 1 1
c^a 0 0
----------------------------
解z3.1的情况:
假设bit1和bit2都是最后两位不同的bit位。
取最后一个1,变为:
bit1 bit2
a^b 1 0
b^c 0 1
c^a 0 1
则(a^b)^(b^c)^(c^a)= 1 0。因为只有a^b = 1 0。
x ^ c = a^b = 1 0这种情况。所以只需要x^每个数据,当出现 1 0的情况下,这个数据就是候选c,但是其他的数字出现偶数,所以用^存储在一个变量中就可以消除相同,最后剩下的就是c。
解z3.2的情况
假设bit1和bit2都是最后两位不同的bit位。
取最后一个1,变为:
bit1 bit2
a^b 0 1
b^c 0 1
c^a 0 0
则(a^b)^(b^c)^(c^a)= 0 0。因为只有a^b = 0 0。因为只有c^a= 0 0。
x^b = c ^ a = 0 0这种情况。所以只需要x^每个数据,当出现 0 0的情况下,这个数据就是候选c,但是其他的数字出现偶数,所以用^存储在一个变量中就可以消除相同,最后剩下的就是b。
-----------------
取出一个数据后,就可以计算剩下的数据。
void Find3(int seq[], int n, int& a, int& b, int& c)
{
XOR
int xors = 0;
for(int i = 0; i < n; i++)
xors ^= seq[i];
int flips = 0;
for(int i = 0; i < n; i++)
flips ^= lowbit(xors ^ seq[i]);
flips = lowbit(flips);
get one of three
a = 0;
for(int i = 0; i < n; i++)
{
if(lowbit(seq[i] ^ xors) == flips)
a ^= seq[i];
}
swap a with the last element of seq
for(int i = 0; i < n; i++)
{
if(a == seq[i])
{
int temp = seq[i];
seq[i] = seq[n - 1];
seq[n - 1] = temp;
}
}
call Find2() to get b and c
Find2(seq, n - 1, b, c);
}
2.寻找无序互异数组中丢失4个数。需要分成4组A,B,C,D,A缺少a,B缺少b,C缺少c,D缺少d
首先s= a^b^c^d。
假设s的某一个bit=0
a,b,c有两种情况
z1.1 z1.2 z1.3
a 1 1 0
b 0 1 0
c 1 1 0
d 0 1 0
假设s的某一个bit=1
z1.4 z1.5
a 0 1
b 1 1
c 0 1
d 0 0
其中z1.2和z1.3的情况是无用的。只有z1.1和z1.4和z1.5可以用来区分
z2.1 z2.2 z2.3 z2.4 z2.5
a^b^c 1 1 1 1 0
a^b^d 1 1 1 0 0
a^c^d 1 1 0 0 0
b^c^d 1 0 0 0 0
-----------------------
z2.1的情况下
z1.2
a 1
b 1
c 1
d 1
z2.2情况下
z1.4
a 1
b 0
c 0
d 0
z2.3情况下
z1.1
a 1
b 1
c 0
d 0
z2.4情况下
z1.5
a 1
b 1
c 1
d 0
z2.5情况下
z1.3
a 0
b 0
c 0
d 0
因为z1.2和z1.3不可用,对应z2.1和z2.5不可用。
剩下3种情况:
z2.2 z2.3 z2.4
a^b^c 1 1 1
a^b^d 1 1 0
a^c^d 1 0 0
b^c^d 0 0 0
讨论z2.2的情况
bit1 bit2
a^b^c 1 1
a^b^d 1 1
a^c^d 1 1
b^c^d 0 0
取最后一个1结果是0 1
bit1 bit2
a^b^c 1 1
a^b^d 0 1
a^c^d 1 1
b^c^d 1 0
取最后一个1结果是1 1
讨论z2.3的情况
bit1 bit2
a^b^c 1 1
a^b^d 1 1
a^c^d 0 0
b^c^d 0 0
取最后一个1结果是 0 0
bit1 bit2
a^b^c 1 1
a^b^d 0 1
a^c^d 0 0
b^c^d 1 0
取最后一个1结果是1 0
bit1 bit2
a^b^c 0 1
a^b^d 0 1
a^c^d 1 0
b^c^d 1 0
取最后一个1结果是 0 0
讨论z2.4的情况
bit1 bit2
a^b^c 1 1
a^b^d 0 0
a^c^d 0 0
b^c^d 0 0
取最后一个1结果是 0 1
bit1 bit2
a^b^c 1 0
a^b^d 0 1
a^c^d 0 0
b^c^d 0 0
取最后一个1结果是 1 1
貌似情况太多了,不可以这么分析。结果再议。