题目:一个整型数组里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是 O(n),空间复杂度是 O(1)。
思路 1:排序后遍历
最直观的思路是:对数组先排序,然后从头到尾遍历,找出只出现一次的数字。但是这种算法的时间复杂度是 $O(n\,log\,n)$。我们需要思考更快的算法。
思路 2:异或
由于数组中绝大多数的数字都是出现两次,我们想要消除掉这些出现两次的数字,很自然的可以想到使用异或操作:相同为 0,相异为 1。但是把数组的所有数字都异或之后,我们最终可以得到的结果是那两个不相同的数字异或的结果。如何将这两个数划分开来呢?我们知道,两个不相同的数字异或的结果肯定不是 0,因此它的二进制表示必然存在某一位等于 1,在这一位上那两个数字中有一个是 0 有一个是 1。因此我们可以将整个数组分为两个类别,一类是这一位是 1 的,另一类是这一位是 0 的,这样就把两个数字划分开了。这时我们再分别对两个类别取异或操作,便能得到两个不同的数字。
总结一下思路:首先把数组中的所有数字进行异或,得到两个不相同数字的异或结果;然后找到这个结果的二进制表示中为 1 的某一位;接着把整个数组按该位为 0 和 1 划分成两类;最后对每一类分别进行异或,便可以得到两个不同的数字。
这个算法的时间复杂度是 O(n),空间复杂度是 O(1)。
实现
1 | // num1, num2 分别为长度为 1 的数组。传出参数 |