国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

LeetCode之SingleNumber以及拓展

2019-11-14 17:47:08
字體:
來源:轉載
供稿:網友

PRoblem 1一個數組中有一個數字a只出現一次,其他數字都出現了兩次。請找出這個只出現一次的數字?

考察知識點:異或運算

思路:比如數字 b^b = 0

           a^0 = a

因此,可以將數組中的所有數字進行異或,而最終異或的結果即為所求只出現一次的數字a.

代碼:

1 def SingleNumber1(Array):2     ret = 03     for i in Array:4         ret ^= i5     return ret

 

 

==========================================================

 

 

Problem 2一個數組中有一個數字a只出現一次,其他數字都出現了三次。請找出這個只出現一次的數字?

考察知識點:位運算

解法一:

考慮用統計的思路來解這道題,如果一個數出現了三次就消掉,int的32個位都是由0/1組成的,所以將所有數的對應位加起來,

再將各位的統計和對3取模,最終剩下的結果就是要找出的數。

例如:數組 [4 7 4 4](這里為了方便,我們取int的最后四位)

        4  0  1  0  0

   7  0  1  1  1

        4  0  1  0  0

        4  0  1  0  0

 Sum      0  4  1  1

Sum%3    0  1  1  1

最后Sum%3得到的結果0111即7,就是我們所要求的Single Number

代碼:

 1 def SingleNumber2_1(Array): 2     ret = 0 3     for i in range(0,32): 4         c = 0 5         d = 1 << i 6         for j in range(0, len(Array)): 7             if Array[j] & d: 8                 c += 1 9         if c % 3:10             ret |= d;11     return ret

 

解法二:

 考慮每一位的統計值,如果累加到3就歸為0,則只會有0/1/2三種情況,所以將大小為32的int數組改為只用兩個int即可。

 第一個int的第i位為0/1代表第i位當前累加有0/1個 1 ,第二個int的第i位為1代表第i位當前累加有2。

當int1和int2中的第i位均為1時,我們將他們都清零。

例如:數組 [4 7 4 4](這里為了方便,我們取int的最后四位)

        4  0  1  0  0

    one     0  1  0  0

     two     0      0  0  0 

=====================

   7  0  1  1  1

     one     0  0  1  1

     two     0      1  0  0 

=====================

        4  0  1  0  0

     one     0  0  0  0

     two     0      0  1  1 

=====================

        4  0  1  0  0

  one     0  1  0  0

     two     0      0  0  0 

=====================

代碼:

 1 def SingleNumber2_2(Array): 2     one = 0 3     two = 0 4     three = 0 5     for i in range(0, len(Array)): 6         two |= (one & Array[i]) 7         one ^= Array[i] 8         three = one & two 9         two -= three10         one -= three11     return one

 

 

==========================================================

 

 

Problem 3一個數組中有兩個數字ab只出現一次,其他數字都出現了兩次。請找出這兩個只出現一次的數字?

思路:若將數組中的所以數字進行異或,那么最終結果為 a ^ b

由于a != b,可以知道a ^ b != 0.即結果肯定有一位為1.

根據那一位,我們知道a,b的那一位肯定一個是0,一個是1.

我們找到為1的那一位i,根據i位為0/1將數組分成兩組,即可將a, b分開。

因此,我們要解決的是兩個Problem 1.

代碼:

 

 1 def SingleNumber3(Array): 2     ret = 0 3     for i in range(0,len(Array)): 4         ret ^= Array[i] 5     pos = 0 6     for j in range(0,32): 7         if (ret>>j) & 1: 8             pos = j 9             break10     sub1,sub2 = split(Array,pos)11     single1 = SingleNumber1(sub1)12     single2 = SingleNumber1(sub2)13     return single1,single214 15 def split(Array, pos):16     sub1 = []17     sub2 = []18     for i in range(0,len(Array)):19         if (Array[i]>>pos) & 1:20             sub1.append(Array[i])21         else:22             sub2.append(Array[i])23     return sub1,sub2
 1 def SingleNumber3(Array): 2     ret = 0 3     for i in range(0,len(Array)): 4         ret ^= Array[i] 5     pos = 0 6     for j in range(0,32): 7         if (ret>>i) & 1: 8             pos = i 9             break10     sub1,sub2 = split(Array,pos)11     single1 = SingleNumber1(sub1)12     single2 = SingleNumber1(sub2)13     return single1,single214 15 def split(Array, pos):16     sub1 = []17     sub2 = []18     for i in range(0,len(Array)):19         if (Array[i]>>pos) & 1:20             sub1.append(Array[i])21         else:22             sub2.append(Array[i])23     return sub1,sub2

 

 

==========================================================

 

 

Problem 4一個數組中有一個數字a只出現一次,其他數字都出現了K次。請找出這個只出現一次的數字?

考察知識點:位運算 and 分情況解決

① K % 2 == 0

基本思路類似于Problem 1

 

② K % 2 == 1

基本思路類似于Problem 2

代碼:

1 def SingleNumber4(Array, k):2     if k % 2 == 0:3         ret = SingleNumber1(Array)4     else:5         ret = SingleNumber2_1(Array)6     return ret

 

 

==========================================================

 

 

Problem 5一個數組中有三個數字abc只出現一次,其他數字都出現了兩次。請找出這三個只出現一次的數字?

思路:此處轉載自:http://zhedahht.blog.163.com/blog/static/25411174201283084246412/

如果我們把數組中所有數字都異或,那最終的結果(記為x)就是abc三個數字的異或結果(x=a^b^c)。其他出現了兩次的數字在異或運算中相互抵消了。

 

我們可以證明異或的結果x不可能是abc三個互不相同的數字中的任何一個。

我們用反證法證明。假設x等于abc中的某一個。比如x等于a,也就是a=a^b^c。因此b^c等于0,即b等于c。這與abc是三個互不相同的三個數相矛盾。

 

由于xabc都各不相同,因此x^ax^bx^c都不等于0

 

我們定義一個函數f(n),它的結果是保留數字n的二進制表示中的最后一位1,而把其他所有位都變成0。比如十進制6表示成二進制是0110

因此f(6)的結果為2(二進制為0010)。f(x^a)f(x^b)f(x^c)的結果均不等于0

接著我們考慮f(x^a)^f(x^b)^f(x^c)的結果。由于對于非0nf(n)的結果的二進制表示中只有一個數位是1,因此f(x^a)^f(x^b)^f(x^c)的結果肯定不為0

于是f(x^a)^f(x^b)^f(x^c)的結果的二進制中至少有一位是1。假設最后一位是1的位是第m位。那么x^ax^bx^c的結果中,有一個或者三個數字的第m位是1

我們使用反正法證明不可能三個數字第m位都是1.

如果x^ax^bx^c的第m位都是1,那么abc三個數字的第m位和x的第m位都相反,因此abc三個數字的第m位相同。如果abc三個數字的第m位都

0x=a^b^c結果的第m位是0。由于xa兩個數字的第m位都是0x^a結果的第m位應該是0。同理可以證明x^bx^cm位都是0。這與我們的假設矛盾。

如果abc三個數字的第m位都是1x=a^b^c結果的第m位是1。由于xa兩個數字的第m位都是1x^a結果的第m位應該是0

同理可以證明x^bx^cm位都是0。這還是與我們的假設矛盾。

因此x^ax^bx^c三個數字中,只有一個數字的第m位是1。于是我們找到了能夠區分abc三個數字的標準。

=============================================================

 

這里我們需要注意上面只是在已知a,b,c的情況下的理論證明,具體編程則有些不一樣:

我們先求得 x = a ^ b ^ c

我們可以將x分別與數組中的元素再進行一次異或,得到一個新的數組,但是并沒有改變數組的特性。

比如與數組中有兩個相等的數字d

那么經過處理之后這兩個數還是相等的,只不過結果為x ^ d 

 

==============================================================

這樣我們可以將數組分成兩部分,這里假設a的m位為1。

則兩個子數組分別為:sub1:包含a   == Problem 1

                           sub2:包含b, c  == Problem2

 

代碼:

 

 1 def SingleNumber5(Array): 2     x = 0 3     for i in range(0,len(Array)): 4         x ^= Array[i] 5     newArray = [] 6     for j in range(0,len(Array)): 7         newArray.append(x^Array[j]) 8     lastOneArrary = func(newArray) 9     ret = 010     for i in range(0,len(lastOneArrary)):11         ret ^= lastOneArrary[i]12     pos = 013     for j in range(0,32):14         if (ret>>j) & 1:15             pos = j16             break17     sub1, sub2 = split(Array,pos)18     print(sub1)19     print(sub2)20     if len(sub1)%2:21         single1 = SingleNumber1(sub1)22         single2, single3 = SingleNumber3(sub2)23     else:24         single1 = SingleNumber1(sub2)25         single2, single3 = SingleNumber3(sub1)26     return single1, single2, single327 28 29 30 def func(Array):31     newArray = []32     for i in range(0,len(Array)):33         pos = 034         for j in range(0,32):35             if (Array[i]>>j) & 1:36                 pos = j37                 break38         newArray.append(1<<pos)39     return newArray

 

 

 


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 永清县| 永康市| 恩平市| 房产| 彰化市| 分宜县| 宣武区| 蒙城县| 綦江县| 卢龙县| 依兰县| 淮安市| 漠河县| 宁乡县| 涞源县| 铅山县| 乌兰县| 长沙县| 高阳县| 正镶白旗| 磴口县| 隆林| 四平市| 星座| 会宁县| 吉林省| 徐闻县| 通江县| 奇台县| 娄烦县| 吴桥县| 祥云县| 石阡县| 团风县| 康马县| 合作市| 凤山县| 两当县| 大厂| 福贡县| 德惠市|