前三題均可以用集合和來求。【sum(set(nums))*N-sum(nums)】windows
一、數組中別的數都出現2次,只有一個數出現1次,找出該數。數組
二、數組中別的數都出現3次,只有一個數出現1次,找出該數。app
三、數組中別的數都出現N次,只有一個數出現1次,找出該數。spa
四、數組中別的數都出現2次,只有兩個數只出現1次,找出這兩個數。.net
五、數組中1到1000遍歷(順序打亂),有兩個數缺失,求出這兩個數。code
def findNum(nums):
if not nums:
return -1
i=0 res=0while i<len(nums): res^=nums[i] return res
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
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中相對應的數變爲負數,最後兩個正數爲所求。