算法19-----(位運算)找出數組中出現只出現一次的數

題目:

前三題均可以用集合和來求。【sum(set(nums))*N-sum(nums)】windows

一、數組中別的數都出現2次,只有一個數出現1次,找出該數。數組

二、數組中別的數都出現3次,只有一個數出現1次,找出該數。app

三、數組中別的數都出現N次,只有一個數出現1次,找出該數。spa

四、數組中別的數都出現2次,只有兩個數只出現1次,找出這兩個數。.net

五、數組中1到1000遍歷(順序打亂),有兩個數缺失,求出這兩個數。code

 解題:

一、(3)第1題至關於第3題N爲偶數。解法思路:數組爲nums,則數組中全部數異或,最後的值爲所求。

def findNum(nums):
  if not nums:
    return -1
i
=0 res=0while i<len(nums): res^=nums[i] return res

二、(3)第2題至關於第3題N爲奇數。解法思路:全部數的二進制位相加 mod 3 ,全部模3值不爲0的位彙總的數即爲所求。

def findNum(nums):
    if not nums:
        return -1
    i=0
    res=0
    bitSum=[0]*4
    while i<4:
        j=0
        while j<len(nums):
            bitSum[i]+=(nums[j]>>i)&1
        res|=(bitSum[i]%3)<<i
        i+=1
    return res

更簡單的解法:一個數用來表示出現一次的位,也就是說這個數的爲1的位就表示這個位上面的數出現過了一次,好比0x10001,就表示bit[0]和bit[4]就是出現過了一次的位。而後再用一個數表示出現過了兩次的位,再用一個數表示出現過了3次的位。只要這個位出現過了3次,我就把這個位拿清除掉,這樣剩餘的最後出現過一次的位的這個數就是咱們要找的數了。blog

def findNum(nums):
    ones=twos=threes=0
    for i in range(len(nums)):
            twos |= ones & A[i]
            ones ^= A[i]
            threes = ones & twos
            ones &= ~threes
            twos &= ~threes
    return ones

 

第4題:先將數組全部數字異或,最後結果就是兩個出現一次的數字相互異或的結果,再將這兩個數分別分在兩個數組中進行異或。如連接:

https://blog.csdn.net/morewindows/article/details/8214003three

    設題目中這兩個只出現1次的數字分別爲A和B,若是能將A,B分開到二個數組中,那顯然符合「異或」解法的關鍵點了。所以這個題目的關鍵點就是將A,B分開到二個數組中。因爲A,B確定是不相等的,所以在二進制上一定有一位是不一樣的。根據這一位是0仍是1能夠將A,B分開到A組和B組。而這個數組中其它數字要麼就屬於A組,要麼就屬於B組。再對A組和B組分別執行「異或」解法就能夠獲得A,B了。而要判斷A,B在哪一位上不相同,只要根據A異或B的結果就能夠知道了,這個結果在二進制上爲1的位都說明A,B在這一位上是不相同的。it

      好比int a[] = {1, 1, 3, 5, 2, 2}class

      整個數組異或的結果爲3^5即 0x0011 ^ 0x0101 = 0x0110

      對0x0110,第1位(由低向高,從0開始)就是1。所以整個數組根據第1位是0仍是1分紅兩組。

      a[0] =1  0x0001  第一組

      a[1] =1  0x0001  第一組

      a[2] =3  0x0011  第二組

      a[3] =5  0x0101  第一組

      a[4] =2  0x0010  第二組

      a[5] =2  0x0010  第二組

      第一組有{1, 1, 5},第二組有{3, 2, 3},明顯對這二組分別執行「異或」解法就能夠獲得5和3了。

def findNum(nums):
    if not nums:
        return -1
    temp=0
    ##先全部數異或獲得A^B的值,A和B爲只出現一次的數
    for item in nums:
        temp^=item
    #找到A和B不一樣的第一位,A^B的第一個1位。該位設爲j位
    j=0
    while j<32:
        if (temp>>j)&1==1:
            break
        j+=1
    A=[]
    B=[]
    #將A、B分到按第j位不一樣分到不一樣組A和B
    for num in nums:
        if (num>>j)&1==1:
            A.append(num)
        else:
            B.append(num)
    ##分到的兩個組所有都異或
    resA=0
    resB=0
    for itemA in A:
        resA^=itemA
    for itemB in B:
        resB^=itemB
    return resA,resB
nums=[1,1,3,5,2,2]
print(findNum(nums))

第5題:思路1:list(set(range(1,1001))-set(nums)),即兩個集合相減

思路2:將nums中相對應的數變爲負數,最後兩個正數爲所求。

相關文章
相關標籤/搜索