[经典算法][Python][异或运算]缺失整数

题目1

一个无序的数组里面有若干个正整数,范围是1-100,其中的99个整数都出现了偶数次,只有1个整数出现了奇数次,如何找到这个出现奇数次的整数?

思路

遍历整个数组,依次做异或运算。由于异或运算在进行运算时,相同为0,不同为1,因此所有出现偶次的整数都会相互抵消成为0,只有唯一出现奇数的整数会被留下。
如:

无序数组 3 1 3 2 4 1 4
异或运算 3 xor 1 xor 3 xor 2 xor 4xor 1 xor 4 xor =2

假设数组长度为n,那么该解法的时间复杂度是O(n),空间复杂度为O(1)。

题目2

假设一个无序数组里有若干个正整数,范围是1-100,其中有98个整数出现了奇数次,其他的整数出现偶数次。如何找出这个2个出现奇次整数?

思路

把2个出现奇数次的整数命名为A和B,遍历整个数组,然后依次做异或运算,进行异或运算的最终结果,等于A和B进行异或运算的结果。在这个结果中,至少有一个二进制单位是1(如果是0,说明A和B相等。和题目不符)
如:无序数组{4,1,2,2,5,1,4,3},所有元素进行异或运算的结果是00000110B

无序数组 4 1 2 2 5 1 4 3
异或运算 1 xor 1 xor 2 xor 2 xor 5xor 1 xor 4 xor 3 xor 00000110B

选定该结果中的值为1的某一位数字,如00000110B的倒数第2位是1,这说明对应的A和B的二进制的倒数第2位是不同的。其中必定有一个是0,有一个是1
根据这个结论可以把原来的数字按照二进制的倒数第2位的不同,分为两个部分,一部分的倒数第2位是0,另外一部分的倒数第2位是1。如:
5—>>二进制—>>101
3—>>二进制—>>011
倒数第2位,一个是0,一个是1
所以按照以上方法可将数组分为:
4,1,5,1,4和2,2,3两个部分。
接下来按照原来的异或运算,从每一部分找出唯一的奇数次即可。
假设数组长度为n,那么该解法的时间复杂度是O(n)。把数组分成两个部分,并不需要额外的存储空间,完全可以按照二进制位分组的同时来做异或运算,所以空间复杂度仍然是O(1)。

代码

def findLostNumber(array):
   # 用于存储出现奇次的整数
   resultList = [0 for i in range(2)]
   # 第一次做整体异或运算
   xorResult = 0;
   for i in array:
       xorResult^=i
   if xorResult==0:
       return None
   # 确定2个整数的不同位,以此来做分组
   separator = 1
   while 0==(xorResult&separator):
       separator<<=1;

   # 第二次分组进行异或运算
   for j in array:
       if 0==(separator&j):
           resultList[0]^=j
       else:
           resultList[1]^=j
   return resultList

if __name__ == '__main__':
   array = [4,1,2,2,5,1,4,3]
   res = findLostNumber(array)
   print(res)

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章