- 題目描述:
- 給定一個包含n個整數的數組,除了一個數出現一次外所有的整數均出現三次,找出這個只出現一次的整數。
- 題目來源:
- http://oj.leetcode.com/problems/single-number-ii/
- 題目分析:
- 對於除出現一次之外的所有的整數,其二進制表示中每一位1出現的次數是3的整數倍,將所有這些1清零,剩下的就是最終的數。
- 用ones記錄到當前計算的變量為止,二進制1出現“1次”(mod 3 之后的 1)的數位。用twos記錄到當前計算的變量為止,二進制1出現“2次”(mod 3 之后的 2)的數位。當ones和twos中的某一位同時為1時表示二進制1出現3次,此時需要清零。即 用二進制模擬三進制計算。最終ones記錄的是最終結果。
- 時間復雜度:O(n)
- 示例代碼:
int singleNumber(int A[], int n) { int ones = 0, twos = 0, xthrees = 0; for(int i = 0; i < n; ++i) { twos |= (ones & A[i]); ones ^= A[i]; xthrees = ~(ones & twos); ones &= xthrees; twos &= xthrees; } return ones; }
擴展一:
給定一個包含n個整數的數組,除了一個數出現二次外所有的整數均出現三次,找出這個只出現二次的整數。ones記錄1出現一次的數,twos記錄1出現2次的數,容易知道twos記錄的即是最終結果。
擴展二:
給定一個包含n個整數的數組,有一個整數x出現b次,一個整數y出現c次,其他所有的數均出現a次,其中b和c均不是a的倍數,找出x和y。使用二進制模擬a進制,累計二進制位1出現的次數,當次數達到a時,對其清零,這樣可以得到b mod a次x,c mod a次y的累加。遍歷剩余結果(用ones、twos、fours...變量表示)中每一位二進制位1出現的次數,如果次數為b mod a 或者 c mod a,可以說明x和y的當前二進制位不同(一個為0,另一個為1),據此二進制位將原數組分成兩組,一組該二進制位為1,另一組該二進制位為0。這樣問題變成“除了一個整數出現a1次(a1 = b 或 a1 = c)外所有的整數均出現a次”,使用和上面相同的方式計算就可以得到最終結果,假設模擬a進制計算過程中使用的變量為ones、twos、fours...那么最終結果可以用ones | twos | fours ...表示。