题目很简单,要求你用O(1)空间求出一个序列中两个出现奇数次的数(其他数都出现偶数次)
另外还有,输入将给出这个序列两遍
提示:解法用到了xor的性质和分类的思想
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
。。
如果只有一个出现奇数次的数,那直接把所有数xor起来就可以了,出现了偶数次的自然会被xor掉
而如果有两个该怎么办呢?
再往下想,如果我们有办法不开数组就“自然”地讲序列“分”成两部分,每一部分都包含了一个出现了奇数次的数,然后问题实际上就解决了,将两个部分分别xor起来即可
现在问题就集中于如何将序列“分”为两部分了
再回到上面将所有数xor起来的做法,设两个出现了奇数次的数为a和b,这样做完之后我们实际上能得到a xor b的值
这个值有什么用呢?异或异或,异就是不同,有不同就能“分”!
这个数在二进制位上有一个1就说明了a和b在这一位上不同,我们实际上可以依据这个来将所有元素分为两个部分,这一位为0和这一位为1
划分的是如此自然,以至于我们可以直接做到O(1)的空间消耗——几个变量就够了
最后的算法像题面一样简单:
第一遍读入序列时将读入的所有数xor起来得到a xor b
取a xor b的某一个不为0的位为基准位
第二遍读入时,将读入元素的基准位为0和1的分别xor起来即可得到a和b
Ps:
其实这题还有另一些“划分”的方法,只是不那么漂亮,也不一定正确,比方说按mod一个数mo分类xor起来,这个做法就相当于是我们之前就默认a,b mod mo的值不同