对于一个数出现一次,和两个数出现一次的问题就不在多做讨论,对于三个数出现一次的问题较为复杂。
1、假设出现一次的三个数分别为a、b、c,首先我们从头到尾异或一遍可以得到x = a^b^c。
然后我们定义一个f(x)表示最后一个不为0的位数,例如x=0101010100,则f(x) = 3。
2、然后从头到尾,对f(x^a)进行异或,我们可以得到flag = f(x^a)^f(x^b)^f(x^c)。
下面我们来解释一下flag怎么得到的:
我们容易得到如下结论:x^a = b^c,x^b = a^c,x^c = a^b,对于其它的可能会有的d,e,f……两次f(x^d)^f(x^d)就会得0,因此最后flag = f(x^a)^f(x^b)^f(x^c)。
首先求出的 f(x^a)至少有一位为1,若f(x^a)为0,则可以得到x = a,那么b = c,与b,c不同不服,因此 f(x^a)至少有一位为1。
因此我们得到结论flag不可能为0,因为flag = f(x^a)^f(x^b)^f(x^c) = f(b^c)^f(a^c)^f(a^b),因为f(x^a)有且仅有1位为1,相异或不可能得到0的结果。
假设得到的flag为1的最低位数是m,则得到:在第m位 f(x^a),f(x^b),f(x^c)中或者其中一个为1,或者三个都为1。
三个都为1是不可能的事情,因为若三个都为1,则意味着 f(b^c),f(a^c),f(a^b)三个数在第m为都为1,即这一位上这三个数互不相同,这是不可能的,因此只能有1个为1。
于是我们得到 f(x^a),f(x^b),f(x^c)三个在第m位只有1个为1,通过第m位我们可以将数组分成两部分。
假设x的第m位为1,则a,b,c三个数只有一个数第m位为0,于是我们可以通过第m位的分组求出这个第m位为0的数。
剩下的问题就是只有2个数出现一次的问题了,就不在做详细的解释。