编辑) 好吧,这种方法并不像我最初想的那么可靠。eBusiness的解决方案对于n=4,m=2这样的情况更简单且正确。
我们可以将异或方法推广到任意的m和n中。我们首先需要选择一个基数b,使得gcd(n, b) = b,且gcd(m, b) < b。由于奇数的n/偶数的m对在基数为2时满足此条件,因此标准二进制异或适用于这些对。
首先,我们定义(a^^n)表示有n个a进行基数为b的一般异或(generalised xor),例如,在标准二进制异或下,a^^2 = 0。
我们需要定义我们的一般异或。我们所需的属性基本上与加法相同(交换律,结合律),并且我们需要a^^b = 0。显然的解决方案是对于基数为b的每个数字,(x^y) = (x+y)%b(让自己相信这个解决方案,它与基数为2的二进制异或相同)。然后,我们将其应用于序列中的所有数字,并最终得到result = s^^(m%b),其中s是特殊数字。
最后,我们需要将'异或'基数为b的数字恢复到预期的数字。我们可以简单地计算每个数字的i^^(m%b),i=0..b-1,然后查找在s中每个数字在result中的哪个值。
此算法为O(N)。对于列表中的每个数字,我们要执行一定数量的操作,因为我们最多有64个数字。对于大的b,最坏情况下的恢复操作为O(N)。我们可以通过计算每个数字的i^^(m%b)来在常量空间内完成此最后一步,对于每个数字都要这样做(同样,我们有一定数量的数字)。
例子:
n = 3,m = 2。列表 = [5 11 5 2 11 5 2 11]
首先,我们选择一个基数b。显然,我们必须选择基数3。
参考异或表:
0|1|2
0|0|1|2
1|1|2|0
2|2|0|1
计算:
5 11 5 2 11 5 2 11
0^0=0. 0^1=1. 1^0=1. 1^0=1. 1^1=2. 2^0=2. 2^0=2. 2^1=0.
0^1=1. 1^0=1. 1^1=2. 2^0=2. 2^0=2. 2^1=0. 0^0=0. 0^0=0.
0^2=2. 2^2=1. 1^2=0. 0^2=2. 2^2=1. 1^2=0. 0^2=2. 2^2=1.
m % b = 2.
因此,我们有 s^^2 = [001]。我们为每个数字 i 生成 i^^2 的表格,然后进行反向查找。
i | 0 | 1 | 2 |
i^^2 | 0 | 2 | 1 |
0 -> 0
0 -> 0
1 -> 2
我们最终将结果转换回二进制/十进制。[002] = 2。