数组中,除了两个数字外其他数字都是成对出现,找出来着两个数字
前一段,同学面试问了一个问题就是标题上的这个问题了。想了一下最起码有一下几种做法。
做法一: 可以对数组进行排序,这样如果数组是成对出现的,那么这相同的数字下标一定相邻,这样只要遍历一遍数组
就可以知道是哪两个数字了。这里可以这么做只需要知道当前数字和当前数字前面的数字不同,而且当前数字和当前数字后面
的数字也不同,那么当前数字就是出现一次的数字了。
做法二: 这个问题还可以这么做,遍历一遍数组将每一个数字出现的次数都记下来,然后遍历记录数组就知道那一个数字是
出现一次的了。看完前面的说法,或许有的同学要说了,这不是桶排序类似的做法吗?和桶排序有区别的就是这里的数组中出现
的数字范围是不太好确定的,而桶排序一般用于那些数组中的数字范围比较小的情况。所以这里的记录数组应用map代替。
做法三: 首先,对数组进行遍历,遍历的同时我们做一个数组元素的异或,这样一遍的遍历下来,我们就得到了两个仅仅出现
一次的数字的异或的结果,然后我们根据二进制异或的原理最终结果的二进制位是1的位置,对两个数字相应的二进制位的位置,
出现的数字一定是不同的。这样我们可以根据最终结果的任意一位二进制位是1的位置,来将这两个数字分开。分开之后我们就是在
所有成对出现的数组中找一个只出现一次的数字。一路异或下去就有了结果。
对三种方法的比较可以知道,对于 1 可能会破坏原有的数组存储结构,或者使用相同的空间大小来复制数组。这样浪费空间,而且
排序的时间复杂度也不小。做法二,使用了额外的数据结构,同样的不好计算。对做法三,我们使用了二进制的计算方法,效率会稍微
高一些,我们在对数组的每一个数字异或之前先判断对方法三我们选定的二进制位是否是1就不需要额外的空间了。同时当第一遍遍历完
成,计算出第一个数字。这时我们不需要再遍历第二次计算第二个数字,而是可以直接将第一个数字和前一遍的遍历结果直接异或得到第二个数字。
这些后续补充都是由网友共同交流获得。欢迎答应评论!