本文參考自《劍指offer》一書,代碼采用Java語言。
題目
在一個數組中除了一個數字只出現一次之外,其他數字都出現了三次。請找出那個只出現一次的數字。
思路
這道題中數字出現了三次,無法像56-1) 數組中只出現一次的兩個數字一樣通過利用異或位運算進行消除相同個數字。但是仍然可以沿用位運算的思路。
將所有數字的二進制表示的對應位都加起來,如果某一位能被三整除,那么只出現一次的數字在該位為0;反之,為1。
測試算例
1.功能測試(唯一出現的數字是0,正數,負數;重復出現的數字是0,正數,負數)
Java代碼
//題目:在一個數組中除了一個數字只出現一次之外,其他數字都出現了三次。請 //找出那個只出現一次的數字。 public class NumberAppearingOnce { public static int findNumberAppearingOnce(int[] arr) { if(arr==null || arr.length<=0) throw new RuntimeException(); int[] bitSum = new int[32]; for(int i=0;i<32;i++) bitSum[i]=0; for(int i=0;i<arr.length;i++) { int bitMask=1; for(int j=31;j>=0;j--) { int bit=arr[i]&bitMask; //注意arr[i]&bitMask不一定等於1或者0,有可能等於00010000 if(bit!=0) bitSum[j]+=1; bitMask=bitMask<<1; } } int result=0; for(int i=0;i<32;i++) { result=result<<1; result+=(bitSum[i]%3); //result=result<<1; //不能放在后面,否則最前面一位就沒了 } return result; } }
收獲
1.判斷某個數x的第n位(如第3位)上是否為1,
1)通過 x&00000100 的結果是否為0 來判斷。(不能根據是否等於1來判斷)
2)通過(x>>3)&1 是否為0 來判斷
2.通過number&bitMask的結果是否為0(不能用1判斷),bitMask=1不斷左移,可以將一個數的二進制存儲到32位的數組中。
int number=100; int bitMask=1; for(int j=31;j>=0;j--) { int bit=number&bitMask; //注意arr[i]&bitMask不一定等於1或者0,有可能等於00010000 if(bit!=0) bits[j]=1; bitMask=bitMask<<1; }
3.通過以下代碼實現二進制轉化為數字(注意左移語句的位置):
int result=0; for(int i=0;i<32;i++) { result=result<<1; result+=bits[i]; //result=result<<1; //不能放在后面,否則最前面一位就沒了 }